generate_syntax.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. #!/usr/bin/env python3
  2. # Copyright (c) 2016 Google Inc.
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. """Generates Vim syntax rules for SPIR-V assembly (.spvasm) files"""
  15. import json
  16. PREAMBLE="""" Vim syntax file
  17. " Language: spvasm
  18. " Generated by SPIRV-Tools
  19. if version < 600
  20. syntax clear
  21. elseif exists("b:current_syntax")
  22. finish
  23. endif
  24. syn case match
  25. """
  26. POSTAMBLE="""
  27. syntax keyword spvasmTodo TODO FIXME contained
  28. syn match spvasmIdNumber /%\d\+\>/
  29. " The assembler treats the leading minus sign as part of the number token.
  30. " This applies to integers, and to floats below.
  31. syn match spvasmNumber /-\?\<\d\+\>/
  32. " Floating point literals.
  33. " In general, C++ requires at least digit in the mantissa, and the
  34. " floating point is optional. This applies to both the regular decimal float
  35. " case and the hex float case.
  36. " First case: digits before the optional decimal, no trailing digits.
  37. syn match spvasmFloat /-\?\d\+\.\?\(e[+-]\d\+\)\?/
  38. " Second case: optional digits before decimal, trailing digits
  39. syn match spvasmFloat /-\?\d*\.\d\+\(e[+-]\d\+\)\?/
  40. " First case: hex digits before the optional decimal, no trailing hex digits.
  41. syn match spvasmFloat /-\?0[xX]\\x\+\.\?p[-+]\d\+/
  42. " Second case: optional hex digits before decimal, trailing hex digits
  43. syn match spvasmFloat /-\?0[xX]\\x*\.\\x\+p[-+]\d\+/
  44. syn match spvasmComment /;.*$/ contains=spvasmTodo
  45. syn region spvasmString start=/"/ skip=/\\\\"/ end=/"/
  46. syn match spvasmId /%[a-zA-Z_][a-zA-Z_0-9]*/
  47. " Highlight unknown constants and statements as errors
  48. syn match spvasmError /[a-zA-Z][a-zA-Z_0-9]*/
  49. if version >= 508 || !exists("did_c_syn_inits")
  50. if version < 508
  51. let did_c_syn_inits = 1
  52. command -nargs=+ HiLink hi link <args>
  53. else
  54. command -nargs=+ HiLink hi def link <args>
  55. endif
  56. HiLink spvasmStatement Statement
  57. HiLink spvasmNumber Number
  58. HiLink spvasmComment Comment
  59. HiLink spvasmString String
  60. HiLink spvasmFloat Float
  61. HiLink spvasmConstant Constant
  62. HiLink spvasmIdNumber Identifier
  63. HiLink spvasmId Identifier
  64. HiLink spvasmTodo Todo
  65. delcommand HiLink
  66. endif
  67. let b:current_syntax = "spvasm"
  68. """
  69. # This list is taken from the description of OpSpecConstantOp in SPIR-V 1.1.
  70. # TODO(dneto): Propose that this information be embedded in the grammar file.
  71. SPEC_CONSTANT_OP_OPCODES = """
  72. OpSConvert, OpFConvert
  73. OpSNegate, OpNot
  74. OpIAdd, OpISub
  75. OpIMul, OpUDiv, OpSDiv, OpUMod, OpSRem, OpSMod
  76. OpShiftRightLogical, OpShiftRightArithmetic, OpShiftLeftLogical
  77. OpBitwiseOr, OpBitwiseXor, OpBitwiseAnd
  78. OpVectorShuffle, OpCompositeExtract, OpCompositeInsert
  79. OpLogicalOr, OpLogicalAnd, OpLogicalNot,
  80. OpLogicalEqual, OpLogicalNotEqual
  81. OpSelect
  82. OpIEqual, OpINotEqual
  83. OpULessThan, OpSLessThan
  84. OpUGreaterThan, OpSGreaterThan
  85. OpULessThanEqual, OpSLessThanEqual
  86. OpUGreaterThanEqual, OpSGreaterThanEqual
  87. OpQuantizeToF16
  88. OpConvertFToS, OpConvertSToF
  89. OpConvertFToU, OpConvertUToF
  90. OpUConvert
  91. OpConvertPtrToU, OpConvertUToPtr
  92. OpGenericCastToPtr, OpPtrCastToGeneric
  93. OpBitcast
  94. OpFNegate
  95. OpFAdd, OpFSub
  96. OpFMul, OpFDiv
  97. OpFRem, OpFMod
  98. OpAccessChain, OpInBoundsAccessChain
  99. OpPtrAccessChain, OpInBoundsPtrAccessChain"""
  100. def EmitAsStatement(name):
  101. """Emits the given name as a statement token"""
  102. print('syn keyword spvasmStatement', name)
  103. def EmitAsEnumerant(name):
  104. """Emits the given name as an named operand token"""
  105. print('syn keyword spvasmConstant', name)
  106. def main():
  107. """Parses arguments, then generates the Vim syntax rules for SPIR-V assembly
  108. on stdout."""
  109. import argparse
  110. parser = argparse.ArgumentParser(description='Generate SPIR-V info tables')
  111. parser.add_argument('--spirv-core-grammar', metavar='<path>',
  112. type=str, required=True,
  113. help='input JSON grammar file for core SPIR-V '
  114. 'instructions')
  115. parser.add_argument('--extinst-glsl-grammar', metavar='<path>',
  116. type=str, required=False, default=None,
  117. help='input JSON grammar file for GLSL extended '
  118. 'instruction set')
  119. parser.add_argument('--extinst-opencl-grammar', metavar='<path>',
  120. type=str, required=False, default=None,
  121. help='input JSON grammar file for OpenGL extended '
  122. 'instruction set')
  123. parser.add_argument('--extinst-debuginfo-grammar', metavar='<path>',
  124. type=str, required=False, default=None,
  125. help='input JSON grammar file for DebugInfo extended '
  126. 'instruction set')
  127. args = parser.parse_args()
  128. # Generate the syntax rules.
  129. print(PREAMBLE)
  130. core = json.loads(open(args.spirv_core_grammar).read())
  131. print('\n" Core instructions')
  132. for inst in core["instructions"]:
  133. EmitAsStatement(inst['opname'])
  134. aliases = inst.get('aliases', [])
  135. for alias in aliases:
  136. EmitAsStatement(alias)
  137. print('\n" Core operand enums')
  138. for operand_kind in core["operand_kinds"]:
  139. if 'enumerants' in operand_kind:
  140. for e in operand_kind['enumerants']:
  141. EmitAsEnumerant(e['enumerant'])
  142. aliases = e.get('aliases', [])
  143. for a in aliases:
  144. EmitAsEnumerant(a)
  145. if args.extinst_glsl_grammar is not None:
  146. print('\n" GLSL.std.450 extended instructions')
  147. glsl = json.loads(open(args.extinst_glsl_grammar).read())
  148. # These opcodes are really enumerant operands for the OpExtInst
  149. # instruction.
  150. for inst in glsl["instructions"]:
  151. EmitAsEnumerant(inst['opname'])
  152. if args.extinst_opencl_grammar is not None:
  153. print('\n" OpenCL.std extended instructions')
  154. opencl = json.loads(open(args.extinst_opencl_grammar).read())
  155. for inst in opencl["instructions"]:
  156. EmitAsEnumerant(inst['opname'])
  157. if args.extinst_debuginfo_grammar is not None:
  158. print('\n" DebugInfo extended instructions')
  159. debuginfo = json.loads(open(args.extinst_debuginfo_grammar).read())
  160. for inst in debuginfo["instructions"]:
  161. EmitAsEnumerant(inst['opname'])
  162. print('\n" DebugInfo operand enums')
  163. for operand_kind in debuginfo["operand_kinds"]:
  164. if 'enumerants' in operand_kind:
  165. for e in operand_kind['enumerants']:
  166. EmitAsEnumerant(e['enumerant'])
  167. print('\n" OpSpecConstantOp opcodes')
  168. for word in SPEC_CONSTANT_OP_OPCODES.split(' '):
  169. stripped = word.strip('\n,')
  170. if stripped != "":
  171. # Treat as an enumerant, but without the leading "Op"
  172. EmitAsEnumerant(stripped[2:])
  173. print(POSTAMBLE)
  174. if __name__ == '__main__':
  175. main()