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