1#encoding=utf-8 2 3import argparse 4import ast 5import intel_genxml 6import re 7import sys 8import copy 9import textwrap 10from util import * 11 12license = """/* 13 * Copyright (C) 2016 Intel Corporation 14 * 15 * Permission is hereby granted, free of charge, to any person obtaining a 16 * copy of this software and associated documentation files (the "Software"), 17 * to deal in the Software without restriction, including without limitation 18 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 19 * and/or sell copies of the Software, and to permit persons to whom the 20 * Software is furnished to do so, subject to the following conditions: 21 * 22 * The above copyright notice and this permission notice (including the next 23 * paragraph) shall be included in all copies or substantial portions of the 24 * Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 29 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 31 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 32 * IN THE SOFTWARE. 33 */ 34""" 35 36pack_header = """%(license)s 37 38/* Instructions, enums and structures for %(platform)s. 39 * 40 * This file has been generated, do not hand edit. 41 */ 42 43#ifndef %(guard)s 44#define %(guard)s 45 46#ifndef __OPENCL_VERSION__ 47#include <stdio.h> 48#include "util/bitpack_helpers.h" 49#include "genX_helpers.h" 50#else 51#include "genX_cl_helpers.h" 52#endif 53 54""" 55 56def num_from_str(num_str): 57 if num_str.lower().startswith('0x'): 58 return int(num_str, base=16) 59 60 assert not num_str.startswith('0'), 'octals numbers not allowed' 61 return int(num_str) 62 63def bool_from_str(bool_str): 64 options = { "true": True, "false": False } 65 return options[bool_str]; 66 67class Field(object): 68 ufixed_pattern = re.compile(r"u(\d+)\.(\d+)") 69 sfixed_pattern = re.compile(r"s(\d+)\.(\d+)") 70 71 def __init__(self, parser, attrs): 72 self.parser = parser 73 if "name" in attrs: 74 self.name = safe_name(attrs["name"]) 75 self.start = int(attrs["start"]) 76 self.end = int(attrs["end"]) 77 self.type = attrs["type"] 78 self.nonzero = bool_from_str(attrs.get("nonzero", "false")) 79 self.prefix = attrs["prefix"] if "prefix" in attrs else None 80 81 assert self.start <= self.end, \ 82 'field {} has end ({}) < start ({})'.format(self.name, self.end, 83 self.start) 84 if self.type == 'bool': 85 assert self.end == self.start, \ 86 'bool field ({}) is too wide'.format(self.name) 87 88 if "default" in attrs: 89 # Base 0 recognizes 0x, 0o, 0b prefixes in addition to decimal ints. 90 self.default = int(attrs["default"], base=0) 91 else: 92 self.default = None 93 94 ufixed_match = Field.ufixed_pattern.match(self.type) 95 if ufixed_match: 96 self.type = 'ufixed' 97 self.fractional_size = int(ufixed_match.group(2)) 98 99 sfixed_match = Field.sfixed_pattern.match(self.type) 100 if sfixed_match: 101 self.type = 'sfixed' 102 self.fractional_size = int(sfixed_match.group(2)) 103 104 def is_builtin_type(self): 105 builtins = [ 'address', 'bool', 'float', 'ufixed', 106 'offset', 'sfixed', 'offset', 'int', 'uint', 107 'mbo', 'mbz' ] 108 return self.type in builtins 109 110 def is_struct_type(self): 111 return self.type in self.parser.structs 112 113 def is_enum_type(self): 114 return self.type in self.parser.enums 115 116 def emit_template_struct(self, dim): 117 if self.type == 'address': 118 type = 'uint64_t' if self.parser.opencl else '__gen_address_type' 119 elif self.type == 'bool': 120 type = 'bool' 121 elif self.type == 'float': 122 type = 'float' 123 elif self.type == 'ufixed': 124 type = 'float' 125 elif self.type == 'sfixed': 126 type = 'float' 127 elif self.type == 'uint' and self.end - self.start > 32: 128 type = 'uint64_t' 129 elif self.type == 'offset': 130 type = 'uint64_t' 131 elif self.type == 'int': 132 type = 'int32_t' 133 elif self.type == 'uint': 134 type = 'uint32_t' 135 elif self.is_struct_type(): 136 type = 'struct ' + self.parser.gen_prefix(safe_name(self.type)) 137 elif self.is_enum_type(): 138 type = 'enum ' + self.parser.gen_prefix(safe_name(self.type)) 139 elif self.type == 'mbo' or self.type == 'mbz': 140 return 141 else: 142 print("#error unhandled type: %s" % self.type) 143 return 144 145 print(" %-36s %s%s;" % (type, self.name, dim)) 146 147 prefix = self.prefix + '_' if self.prefix else '' 148 149 for value in self.values: 150 name = value.name 151 if self.prefix and value.name[0] == '_': 152 name = name[1:] 153 154 print("#define %-40s %d" % (prefix + name, value.value)) 155 156class Group(object): 157 def __init__(self, parser, parent, start, count, size): 158 self.parser = parser 159 self.parent = parent 160 self.start = start 161 self.count = count 162 self.size = size 163 self.fields = [] 164 165 def emit_template_struct(self, dim): 166 if self.count == 0: 167 print(" /* variable length fields follow */") 168 else: 169 if self.count > 1: 170 dim = "%s[%d]" % (dim, self.count) 171 172 for field in self.fields: 173 field.emit_template_struct(dim) 174 175 class DWord: 176 def __init__(self): 177 self.size = 32 178 self.fields = [] 179 self.address = None 180 181 def collect_dwords(self, dwords, start, dim): 182 for field in self.fields: 183 if isinstance(field, Group): 184 if field.count == 1: 185 field.collect_dwords(dwords, start + field.start, dim) 186 else: 187 for i in range(field.count): 188 field.collect_dwords(dwords, 189 start + field.start + i * field.size, 190 "%s[%d]" % (dim, i)) 191 continue 192 193 index = (start + field.start) // 32 194 if not index in dwords: 195 dwords[index] = self.DWord() 196 197 clone = copy.copy(field) 198 clone.start = clone.start + start 199 clone.end = clone.end + start 200 clone.dim = dim 201 dwords[index].fields.append(clone) 202 203 if field.type == "address": 204 # assert dwords[index].address == None 205 dwords[index].address = clone 206 207 # Coalesce all the dwords covered by this field. The two cases we 208 # handle are where multiple fields are in a 64 bit word (typically 209 # and address and a few bits) or where a single struct field 210 # completely covers multiple dwords. 211 while index < (start + field.end) // 32: 212 if index + 1 in dwords and not dwords[index] == dwords[index + 1]: 213 dwords[index].fields.extend(dwords[index + 1].fields) 214 dwords[index].size = 64 215 dwords[index + 1] = dwords[index] 216 index = index + 1 217 218 def collect_dwords_and_length(self, repack=False): 219 dwords = {} 220 self.collect_dwords(dwords, 0, "") 221 222 # Determine number of dwords in this group. If we have a size, use 223 # that, since that'll account for MBZ dwords at the end of a group 224 # (like dword 8 on BDW+ 3DSTATE_HS). Otherwise, use the largest dword 225 # index we've seen plus one. 226 if self.size > 0: 227 length = self.size // 32 228 elif dwords: 229 length = max(dwords.keys()) + 1 230 else: 231 length = 0 232 233 return (dwords, length) 234 235 def emit_pack_function(self, dwords, length, repack=False): 236 for index in range(length): 237 # Handle MBZ dwords 238 if not index in dwords: 239 print("") 240 print(" dw[%d] = 0;" % index) 241 continue 242 243 # For 64 bit dwords, we aliased the two dword entries in the dword 244 # dict it occupies. Now that we're emitting the pack function, 245 # skip the duplicate entries. 246 dw = dwords[index] 247 if index > 0 and index - 1 in dwords and dw == dwords[index - 1]: 248 continue 249 250 # Special case: only one field and it's a struct at the beginning 251 # of the dword. In this case we pack directly into the 252 # destination. This is the only way we handle embedded structs 253 # larger than 32 bits. 254 if len(dw.fields) == 1: 255 field = dw.fields[0] 256 name = field.name + field.dim 257 if field.is_struct_type() and field.start % 32 == 0: 258 print("") 259 if repack: 260 if self.parser.opencl: 261 print(" %s_repack(&dw[%d], &origin[%d], &values->%s);" % 262 (self.parser.gen_prefix(safe_name(field.type)), index, index, name)) 263 else: 264 print(" %s_pack(data, &dw[%d], &origin[%d], &values->%s);" % 265 (self.parser.gen_prefix(safe_name(field.type)), index, index, name)) 266 else: 267 if self.parser.opencl: 268 print(" %s_pack(&dw[%d], &values->%s);" % 269 (self.parser.gen_prefix(safe_name(field.type)), index, name)) 270 else: 271 print(" %s_pack(data, &dw[%d], &values->%s);" % 272 (self.parser.gen_prefix(safe_name(field.type)), index, name)) 273 continue 274 275 # Pack any fields of struct type first so we have integer values 276 # to the dword for those fields. 277 field_index = 0 278 for field in dw.fields: 279 if isinstance(field, Field) and field.is_struct_type(): 280 name = field.name + field.dim 281 print("") 282 print(" uint32_t v%d_%d;" % (index, field_index)) 283 if repack: 284 if self.parser.opencl: 285 print(" %s_repack(&v%d_%d, &origin[%d], &values->%s);" % 286 (self.parser.gen_prefix(safe_name(field.type)), index, field_index, index, name)) 287 else: 288 print(" %s_repack(data, &v%d_%d, &origin[%d], &values->%s);" % 289 (self.parser.gen_prefix(safe_name(field.type)), index, field_index, index, name)) 290 else: 291 if self.parser.opencl: 292 print(" %s_pack(&v%d_%d, &values->%s);" % 293 (self.parser.gen_prefix(safe_name(field.type)), index, field_index, name)) 294 else: 295 print(" %s_pack(data, &v%d_%d, &values->%s);" % 296 (self.parser.gen_prefix(safe_name(field.type)), index, field_index, name)) 297 field_index = field_index + 1 298 299 print("") 300 dword_start = index * 32 301 if dw.address == None: 302 address_count = 0 303 else: 304 address_count = 1 305 306 # Assert in dont_use values 307 for field in dw.fields: 308 for value in field.values: 309 if value.dont_use: 310 print(" assert(values->%s != %s);" % 311 (field.name, field.prefix + "_" + value.name)) 312 313 if dw.size == 32 and dw.address == None: 314 v = None 315 print(" dw[%d] =" % index) 316 elif len(dw.fields) > address_count or repack: 317 v = "v%d" % index 318 print(" const uint%d_t %s =" % (dw.size, v)) 319 else: 320 v = "0" 321 322 field_index = 0 323 non_address_fields = [] 324 325 if repack: 326 non_address_fields.append("origin[%d]" % index) 327 if dw.size > 32: 328 non_address_fields.append("((uint64_t)origin[%d] << 32)" % (index + 1)) 329 330 for field in dw.fields: 331 if field.type != "mbo" and field.type != "mbz" and field.type != "repack": 332 name = field.name + field.dim 333 334 nz = "_nonzero" if field.nonzero else "" 335 336 if field.type == "repack": 337 non_address_fields.append("origin[%d]" % index) 338 elif field.type == "mbo": 339 non_address_fields.append("util_bitpack_ones(%d, %d)" % \ 340 (field.start - dword_start, field.end - dword_start)) 341 elif field.type == "mbz": 342 assert not field.nonzero 343 elif field.type == "address": 344 pass 345 elif field.type == "uint": 346 non_address_fields.append("util_bitpack_uint%s(values->%s, %d, %d)" % \ 347 (nz, name, field.start - dword_start, field.end - dword_start)) 348 elif field.is_enum_type(): 349 non_address_fields.append("util_bitpack_uint%s(values->%s, %d, %d)" % \ 350 (nz, name, field.start - dword_start, field.end - dword_start)) 351 elif field.type == "int": 352 non_address_fields.append("util_bitpack_sint%s(values->%s, %d, %d)" % \ 353 (nz, name, field.start - dword_start, field.end - dword_start)) 354 elif field.type == "bool": 355 non_address_fields.append("util_bitpack_uint%s(values->%s, %d, %d)" % \ 356 (nz, name, field.start - dword_start, field.end - dword_start)) 357 elif field.type == "float": 358 non_address_fields.append("util_bitpack_float%s(values->%s)" % (nz, name)) 359 elif field.type == "offset": 360 non_address_fields.append("__gen_offset%s(values->%s, %d, %d)" % \ 361 (nz, name, field.start - dword_start, field.end - dword_start)) 362 elif field.type == 'ufixed': 363 non_address_fields.append("util_bitpack_ufixed%s(values->%s, %d, %d, %d)" % \ 364 (nz, name, field.start - dword_start, field.end - dword_start, field.fractional_size)) 365 elif field.type == 'sfixed': 366 non_address_fields.append("util_bitpack_sfixed%s(values->%s, %d, %d, %d)" % \ 367 (nz, name, field.start - dword_start, field.end - dword_start, field.fractional_size)) 368 elif field.is_struct_type(): 369 non_address_fields.append("util_bitpack_uint(v%d_%d, %d, %d)" % \ 370 (index, field_index, field.start - dword_start, field.end - dword_start)) 371 field_index = field_index + 1 372 else: 373 non_address_fields.append("/* unhandled field %s, type %s */\n" % \ 374 (name, field.type)) 375 376 if non_address_fields: 377 print(" |\n".join(" " + f for f in non_address_fields) + ";") 378 379 if dw.size == 32: 380 if dw.address: 381 if self.parser.opencl: 382 print(" dw[%d] = __gen_address(values->%s, %d, %d) | %s;" % 383 (index, dw.address.name + field.dim, 384 dw.address.start - dword_start, dw.address.end - dword_start, v)) 385 else: 386 print(" dw[%d] = __gen_address(data, &dw[%d], values->%s, %s, %d, %d);" % 387 (index, index, dw.address.name + field.dim, v, 388 dw.address.start - dword_start, dw.address.end - dword_start)) 389 continue 390 391 if dw.address: 392 v_address = "v%d_address" % index 393 if self.parser.opencl: 394 print(" const uint64_t %s =\n __gen_address(values->%s, %d, %d) | %s;" % 395 (v_address, dw.address.name + field.dim, 396 dw.address.start - dword_start, dw.address.end - dword_start, v)) 397 else: 398 print(" const uint64_t %s =\n __gen_address(data, &dw[%d], values->%s, %s, %d, %d);" % 399 (v_address, index, dw.address.name + field.dim, v, 400 dw.address.start - dword_start, dw.address.end - dword_start)) 401 if len(dw.fields) > address_count: 402 print(" dw[%d] = %s;" % (index, v_address)) 403 print(" dw[%d] = (%s >> 32) | (%s >> 32);" % (index + 1, v_address, v)) 404 continue 405 else: 406 v = v_address 407 print(" dw[%d] = %s;" % (index, v)) 408 print(" dw[%d] = %s >> 32;" % (index + 1, v)) 409 410class Value(object): 411 def __init__(self, attrs): 412 self.name = safe_name(attrs["name"]) 413 self.value = ast.literal_eval(attrs["value"]) 414 self.dont_use = int(attrs["dont_use"]) != 0 if "dont_use" in attrs else False 415 416class Parser(object): 417 def __init__(self, opencl, repack): 418 self.instruction = None 419 self.structs = {} 420 # Set of enum names we've seen. 421 self.enums = set() 422 self.registers = {} 423 self.opencl = opencl 424 self.repack = repack 425 426 def gen_prefix(self, name): 427 if name[0] == "_": 428 return 'GFX%s%s' % (self.gen, name) 429 return 'GFX%s_%s' % (self.gen, name) 430 431 def gen_guard(self): 432 if self.opencl: 433 return self.gen_prefix("{0}_CL_PACK_H".format(self.platform)) 434 return self.gen_prefix("{0}_PACK_H".format(self.platform)) 435 436 def process_item(self, item): 437 name = item.tag 438 assert name != "genxml" 439 attrs = item.attrib 440 441 if name in ("instruction", "struct", "register"): 442 if name == "instruction": 443 self.instruction = safe_name(attrs["name"]) 444 self.length_bias = int(attrs["bias"]) 445 elif name == "struct": 446 self.struct = safe_name(attrs["name"]) 447 self.structs[attrs["name"]] = 1 448 elif name == "register": 449 self.register = safe_name(attrs["name"]) 450 self.reg_num = num_from_str(attrs["num"]) 451 self.registers[attrs["name"]] = 1 452 if "length" in attrs: 453 self.length = int(attrs["length"]) 454 size = self.length * 32 455 else: 456 self.length = None 457 size = 0 458 self.group = Group(self, None, 0, 1, size) 459 460 elif name == "group": 461 group = Group(self, self.group, 462 int(attrs["start"]), int(attrs["count"]), int(attrs["size"])) 463 self.group.fields.append(group) 464 self.group = group 465 elif name == "field": 466 self.group.fields.append(Field(self, attrs)) 467 self.values = [] 468 elif name == "enum": 469 self.values = [] 470 self.enum = safe_name(attrs["name"]) 471 self.enums.add(attrs["name"]) 472 if "prefix" in attrs: 473 self.prefix = safe_name(attrs["prefix"]) 474 else: 475 self.prefix = None 476 elif name == "value": 477 self.values.append(Value(attrs)) 478 elif name in ("import", "exclude"): 479 pass 480 else: 481 assert False 482 483 for child_item in item: 484 self.process_item(child_item) 485 486 if name == "instruction": 487 self.emit_instruction() 488 self.instruction = None 489 self.group = None 490 elif name == "struct": 491 self.emit_struct() 492 self.struct = None 493 self.group = None 494 elif name == "register": 495 self.emit_register() 496 self.register = None 497 self.reg_num = None 498 self.group = None 499 elif name == "group": 500 self.group = self.group.parent 501 elif name == "field": 502 self.group.fields[-1].values = self.values 503 elif name == "enum": 504 self.emit_enum() 505 self.enum = None 506 elif name in ("import", "exclude", "value"): 507 pass 508 else: 509 assert False 510 511 def emit_template_struct(self, name, group): 512 print("struct %s {" % self.gen_prefix(name)) 513 group.emit_template_struct("") 514 print("};\n") 515 516 def emit_pack_function(self, name, group, repack=False): 517 name = self.gen_prefix(name) 518 if repack: 519 if self.opencl: 520 print(textwrap.dedent("""\ 521 static inline __attribute__((always_inline)) void 522 %s_repack(__attribute__((unused)) global void * restrict dst, 523 %s__attribute__((unused)) global const uint32_t * origin, 524 %s__attribute__((unused)) private const struct %s * restrict values) 525 {""") % (name, ' ' * len(name), ' ' * len(name), name)) 526 else: 527 print(textwrap.dedent("""\ 528 static inline __attribute__((always_inline)) void 529 %s_repack(__attribute__((unused)) __gen_user_data *data, 530 %s__attribute__((unused)) void * restrict dst, 531 %s__attribute__((unused)) global const uint32_t * origin, 532 %s__attribute__((unused)) const struct %s * restrict values) 533 {""") % (name, ' ' * len(name), ' ' * len(name), ' ' * len(name), name)) 534 else: 535 if self.opencl: 536 print(textwrap.dedent("""\ 537 static inline __attribute__((always_inline)) void 538 %s_pack(__attribute__((unused)) global void * restrict dst, 539 %s__attribute__((unused)) private const struct %s * restrict values) 540 {""") % (name, ' ' * len(name), name)) 541 else: 542 print(textwrap.dedent("""\ 543 static inline __attribute__((always_inline)) void 544 %s_pack(__attribute__((unused)) __gen_user_data *data, 545 %s__attribute__((unused)) void * restrict dst, 546 %s__attribute__((unused)) const struct %s * restrict values) 547 {""") % (name, ' ' * len(name), ' ' * len(name), name)) 548 549 (dwords, length) = group.collect_dwords_and_length(repack) 550 if length: 551 # Cast dst to make header C++ friendly 552 type_name = "global uint32_t *" if self.opencl else "uint32_t * restrict" 553 print(" %s dw = (%s) dst;" % (type_name, type_name)) 554 555 group.emit_pack_function(dwords, length, repack) 556 557 print("}\n") 558 559 def emit_instruction(self): 560 name = self.instruction 561 562 if not self.length is None: 563 print('#define %-33s %6d' % 564 (self.gen_prefix(name + "_length"), self.length)) 565 print('#define %-33s %6d' % 566 (self.gen_prefix(name + "_length_bias"), self.length_bias)) 567 568 default_fields = [] 569 for field in self.group.fields: 570 if not isinstance(field, Field): 571 continue 572 if field.default is None: 573 continue 574 575 if field.is_builtin_type(): 576 default_fields.append(" .%-35s = %6d" % (field.name, field.default)) 577 else: 578 # Default values should not apply to structures 579 assert field.is_enum_type() 580 default_fields.append(" .%-35s = (enum %s) %6d" % (field.name, self.gen_prefix(safe_name(field.type)), field.default)) 581 582 if default_fields: 583 print('#define %-40s\\' % (self.gen_prefix(name + '_header'))) 584 print(", \\\n".join(default_fields)) 585 print('') 586 587 self.emit_template_struct(self.instruction, self.group) 588 self.emit_pack_function(self.instruction, self.group) 589 if self.repack: 590 self.emit_pack_function(self.instruction, self.group, repack=True) 591 592 def emit_register(self): 593 name = self.register 594 if not self.reg_num is None: 595 print('#define %-33s 0x%04x' % 596 (self.gen_prefix(name + "_num"), self.reg_num)) 597 598 if not self.length is None: 599 print('#define %-33s %6d' % 600 (self.gen_prefix(name + "_length"), self.length)) 601 602 self.emit_template_struct(self.register, self.group) 603 self.emit_pack_function(self.register, self.group) 604 605 def emit_struct(self): 606 name = self.struct 607 if not self.length is None: 608 print('#define %-33s %6d' % 609 (self.gen_prefix(name + "_length"), self.length)) 610 611 self.emit_template_struct(self.struct, self.group) 612 self.emit_pack_function(self.struct, self.group) 613 if self.repack: 614 self.emit_pack_function(self.struct, self.group, repack=True) 615 616 def emit_enum(self): 617 print('enum %s {' % self.gen_prefix(self.enum)) 618 for value in self.values: 619 if self.prefix: 620 name = self.prefix + "_" + value.name 621 else: 622 name = value.name 623 print(' %-36s = %6d,' % (name.upper(), value.value)) 624 print('};\n') 625 626 def emit_genxml(self, genxml): 627 root = genxml.et.getroot() 628 self.platform = root.attrib["name"] 629 self.gen = root.attrib["gen"].replace('.', '') 630 print(pack_header % {'license': license, 'platform': self.platform, 'guard': self.gen_guard()}) 631 for item in root: 632 self.process_item(item) 633 print('#endif /* %s */' % self.gen_guard()) 634 635def parse_args(): 636 p = argparse.ArgumentParser() 637 p.add_argument('xml_source', metavar='XML_SOURCE', 638 help="Input xml file") 639 p.add_argument('--engines', nargs='?', type=str, default='render', 640 help="Comma-separated list of engines whose instructions should be parsed (default: %(default)s)") 641 p.add_argument('--include-symbols', nargs='?', type=str, action='store', 642 help="List of instruction/structures to generate") 643 p.add_argument('--opencl', action='store_true', help="Generate OpenCL code") 644 p.add_argument('--repack', action='store_true', help="Emit repacking code") 645 646 pargs = p.parse_args() 647 648 if pargs.engines is None: 649 print("No engines specified") 650 sys.exit(1) 651 652 return pargs 653 654def main(): 655 pargs = parse_args() 656 657 engines = set(pargs.engines.split(',')) 658 valid_engines = [ 'render', 'blitter', 'video' ] 659 if engines - set(valid_engines): 660 print("Invalid engine specified, valid engines are:\n") 661 for e in valid_engines: 662 print("\t%s" % e) 663 sys.exit(1) 664 665 genxml = intel_genxml.GenXml(pargs.xml_source) 666 667 genxml.merge_imported() 668 genxml.filter_engines(engines) 669 if pargs.include_symbols: 670 genxml.filter_symbols(pargs.include_symbols.split(',')) 671 p = Parser(pargs.opencl, pargs.repack) 672 p.emit_genxml(genxml) 673 674if __name__ == '__main__': 675 main() 676