1COPYRIGHT = """\ 2/* 3 * Copyright (C) 2017 Intel Corporation 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 */ 24""" 25 26import argparse 27import json 28from sys import stdout 29from mako.template import Template 30 31def collect_data(spirv, kind): 32 for x in spirv["operand_kinds"]: 33 if x["kind"] == kind: 34 operands = x 35 break 36 37 values = {} 38 for x in operands["enumerants"]: 39 name = x["enumerant"] 40 val = x["value"] 41 if val not in values: 42 values[val] = [name] 43 else: 44 values[val].append(name) 45 46 return (kind, list(values.values()), operands["category"]) 47 48def collect_opcodes(spirv): 49 seen = set() 50 values = [] 51 for x in spirv["instructions"]: 52 # Handle aliases by choosing the first one in the grammar. 53 # E.g. OpDecorateString and OpDecorateStringGOOGLE share same opcode. 54 if x["opcode"] in seen: 55 continue 56 opcode = x["opcode"] 57 name = x["opname"] 58 assert name.startswith("Op") 59 values.append([name[2:]]) 60 seen.add(opcode) 61 62 return ("Op", values, None) 63 64def parse_args(): 65 p = argparse.ArgumentParser() 66 p.add_argument('--out-c', required=True, help='Output C file.') 67 p.add_argument('--out-h', required=True, help='Output H file.') 68 p.add_argument('--json', required=True, help='SPIR-V JSON file.') 69 return p.parse_args() 70 71TEMPLATE_H = Template("""\ 72/* DO NOT EDIT - This file is generated automatically by spirv_info_c.py script */ 73 74""" + COPYRIGHT + """\ 75 76#ifndef _SPIRV_INFO_H_ 77#define _SPIRV_INFO_H_ 78 79#include <stdbool.h> 80 81#include "compiler/spirv/spirv.h" 82 83% for kind,values,category in info: 84% if kind == "Capability": 85struct spirv_capabilities { 86 % for names in values: 87 % if len(names) == 1: 88 bool ${names[0]}; 89 % else: 90 union { 91 % for name in names: 92 bool ${name}; 93 % endfor 94 }; 95 % endif 96 % endfor 97}; 98% endif 99% endfor 100 101bool spirv_capabilities_get(const struct spirv_capabilities *caps, 102 SpvCapability cap); 103void spirv_capabilities_set(struct spirv_capabilities *caps, 104 SpvCapability cap, bool enabled); 105 106% for kind,values,category in info: 107% if category == "BitEnum": 108const char *spirv_${kind.lower()}_to_string(Spv${kind}Mask v); 109% else: 110const char *spirv_${kind.lower()}_to_string(Spv${kind} v); 111% endif 112% endfor 113 114#endif /* SPIRV_INFO_H */ 115""") 116 117TEMPLATE_C = Template("""\ 118/* DO NOT EDIT - This file is generated automatically by spirv_info_c.py script */ 119 120""" + COPYRIGHT + """\ 121#include "spirv_info.h" 122 123#include "util/macros.h" 124 125% for kind,values,category in info: 126% if kind == "Capability": 127bool 128spirv_capabilities_get(const struct spirv_capabilities *caps, 129 SpvCapability cap) 130{ 131 switch (cap) { 132 % for names in values: 133 case SpvCapability${names[0]}: return caps->${names[0]}; 134 % endfor 135 default: 136 return false; 137 } 138} 139 140void 141spirv_capabilities_set(struct spirv_capabilities *caps, 142 SpvCapability cap, bool enabled) 143{ 144 switch (cap) { 145 % for names in values: 146 case SpvCapability${names[0]}: caps->${names[0]} = enabled; break; 147 % endfor 148 default: 149 unreachable("Unknown capability"); 150 } 151} 152% endif 153% endfor 154 155% for kind,values,category in info: 156 157% if category == "BitEnum": 158const char * 159spirv_${kind.lower()}_to_string(Spv${kind}Mask v) 160{ 161 switch (v) { 162 % for names in values: 163 %if names[0] != "None": 164 case Spv${kind}${names[0]}Mask: return "Spv${kind}${names[0]}"; 165 % else: 166 case Spv${kind}MaskNone: return "Spv${kind}${names[0]}"; 167 % endif 168 % endfor 169 } 170 171 return "unknown"; 172} 173% else: 174const char * 175spirv_${kind.lower()}_to_string(Spv${kind} v) 176{ 177 switch (v) { 178 % for names in values: 179 case Spv${kind}${names[0]}: return "Spv${kind}${names[0]}"; 180 % endfor 181 case Spv${kind}Max: break; /* silence warnings about unhandled enums. */ 182 } 183 184 return "unknown"; 185} 186% endif 187% endfor 188""") 189 190if __name__ == "__main__": 191 pargs = parse_args() 192 193 spirv_info = json.JSONDecoder().decode(open(pargs.json, "r").read()) 194 195 info = [ 196 collect_data(spirv_info, "AddressingModel"), 197 collect_data(spirv_info, "BuiltIn"), 198 collect_data(spirv_info, "Capability"), 199 collect_data(spirv_info, "Decoration"), 200 collect_data(spirv_info, "Dim"), 201 collect_data(spirv_info, "ExecutionMode"), 202 collect_data(spirv_info, "ExecutionModel"), 203 collect_data(spirv_info, "FPRoundingMode"), 204 collect_data(spirv_info, "FunctionParameterAttribute"), 205 collect_data(spirv_info, "ImageFormat"), 206 collect_data(spirv_info, "ImageOperands"), 207 collect_data(spirv_info, "MemoryModel"), 208 collect_data(spirv_info, "StorageClass"), 209 collect_opcodes(spirv_info), 210 ] 211 212 with open(pargs.out_h, 'w', encoding='utf-8') as f: 213 f.write(TEMPLATE_H.render(info=info)) 214 with open(pargs.out_c, 'w', encoding='utf-8') as f: 215 f.write(TEMPLATE_C.render(info=info)) 216