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