From 8a5069e81f91d8ee4dad35f303782e6ce0b27391 Mon Sep 17 00:00:00 2001 From: Tim Rowley Date: Wed, 15 Mar 2017 13:37:50 -0500 Subject: [PATCH] swr: [rasterizer codegen] Rewrite gen_llvm_types.py to use mako Reviewed-by: Bruce Cherniak --- src/gallium/drivers/swr/Makefile.am | 9 +- src/gallium/drivers/swr/SConscript | 2 +- .../swr/rasterizer/codegen/gen_llvm_types.py | 206 ++++++++---------- .../rasterizer/codegen/templates/gen_llvm.hpp | 72 ++++++ 4 files changed, 171 insertions(+), 118 deletions(-) create mode 100644 src/gallium/drivers/swr/rasterizer/codegen/templates/gen_llvm.hpp diff --git a/src/gallium/drivers/swr/Makefile.am b/src/gallium/drivers/swr/Makefile.am index 771f1a82439..99a7df5f6c4 100644 --- a/src/gallium/drivers/swr/Makefile.am +++ b/src/gallium/drivers/swr/Makefile.am @@ -65,11 +65,11 @@ BUILT_SOURCES = \ MKDIR_GEN = $(AM_V_at)$(MKDIR_P) $(@D) PYTHON_GEN = $(AM_V_GEN)$(PYTHON2) $(PYTHON_FLAGS) -swr_context_llvm.h: rasterizer/codegen/gen_llvm_types.py swr_context.h +swr_context_llvm.h: rasterizer/codegen/gen_llvm_types.py rasterizer/codegen/templates/gen_llvm.hpp swr_context.h $(PYTHON_GEN) \ $(srcdir)/rasterizer/codegen/gen_llvm_types.py \ --input $(srcdir)/swr_context.h \ - --output swr_context_llvm.h + --output ./swr_context_llvm.h rasterizer/codegen/gen_knobs.cpp: rasterizer/codegen/gen_knobs.py rasterizer/codegen/knob_defs.py rasterizer/codegen/templates/knobs_template.cpp $(MKDIR_GEN) @@ -87,7 +87,7 @@ rasterizer/codegen/gen_knobs.h: rasterizer/codegen/gen_knobs.py rasterizer/codeg --output rasterizer/codegen/gen_knobs.h \ --gen_h -rasterizer/jitter/state_llvm.h: rasterizer/codegen/gen_llvm_types.py rasterizer/core/state.h +rasterizer/jitter/state_llvm.h: rasterizer/codegen/gen_llvm_types.py rasterizer/codegen/templates/gen_llvm.hpp rasterizer/core/state.h $(MKDIR_GEN) $(PYTHON_GEN) \ $(srcdir)/rasterizer/codegen/gen_llvm_types.py \ @@ -264,4 +264,5 @@ EXTRA_DIST = \ rasterizer/codegen/templates/ar_eventhandler_h.template \ rasterizer/codegen/templates/ar_eventhandlerfile_h.template \ rasterizer/codegen/templates/backend_template.cpp \ - rasterizer/codegen/templates/gen_builder_template.hpp + rasterizer/codegen/templates/gen_builder_template.hpp \ + rasterizer/codegen/templates/gen_llvm.hpp diff --git a/src/gallium/drivers/swr/SConscript b/src/gallium/drivers/swr/SConscript index 754e6784f2e..efcc686aaa7 100644 --- a/src/gallium/drivers/swr/SConscript +++ b/src/gallium/drivers/swr/SConscript @@ -84,7 +84,7 @@ env.CodeGenerate( ) env.CodeGenerate( - target = 'swr_context_llvm.h', + target = './swr_context_llvm.h', script = swrroot + 'rasterizer/codegen/gen_llvm_types.py', source = 'swr_context.h', command = python_cmd + ' $SCRIPT --input $SOURCE --output $TARGET' diff --git a/src/gallium/drivers/swr/rasterizer/codegen/gen_llvm_types.py b/src/gallium/drivers/swr/rasterizer/codegen/gen_llvm_types.py index e88158c14d8..72e67978d9f 100644 --- a/src/gallium/drivers/swr/rasterizer/codegen/gen_llvm_types.py +++ b/src/gallium/drivers/swr/rasterizer/codegen/gen_llvm_types.py @@ -1,4 +1,4 @@ -# Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved. +# Copyright (C) 2014-2017 Intel Corporation. All Rights Reserved. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -19,62 +19,36 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -#!deps/python32/python.exe - +from __future__ import print_function import os, sys, re import argparse import json as JSON import operator - -header = r""" -/**************************************************************************** -* Copyright (C) 2014-2016 Intel Corporation. All Rights Reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a -* copy of this software and associated documentation files (the "Software"), -* to deal in the Software without restriction, including without limitation -* the rights to use, copy, modify, merge, publish, distribute, sublicense, -* and/or sell copies of the Software, and to permit persons to whom the -* Software is furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice (including the next -* paragraph) shall be included in all copies or substantial portions of the -* Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -* IN THE SOFTWARE. -* -* @file %s -* -* @brief auto-generated file -* -* DO NOT EDIT -* -******************************************************************************/ - -#pragma once - -namespace SwrJit -{ - using namespace llvm; - -""" - -""" -""" -def gen_file_header(filename): - global header - headerStr = header % filename - return headerStr.splitlines() - -""" -""" -def gen_llvm_type(type, name, postfix_name, is_pointer, is_pointer_pointer, is_array, is_array_array, array_count, array_count1, is_llvm_struct, is_llvm_enum, is_llvm_pfn, output_file): +from mako.template import Template +from mako.exceptions import RichTraceback + +def write_template_to_string(template_filename, **kwargs): + try: + template = Template(filename=os.path.abspath(template_filename)) + # Split + Join fixes line-endings for whatever platform you are using + return '\n'.join(template.render(**kwargs).splitlines()) + except: + traceback = RichTraceback() + for (filename, lineno, function, line) in traceback.traceback: + print('File %s, line %s, in %s' % (filename, lineno, function)) + print(line, '\n') + print('%s: %s' % (str(traceback.error.__class__.__name__), traceback.error)) + +def write_template_to_file(template_filename, output_filename, **kwargs): + output_dirname = os.path.dirname(output_filename) + if not os.path.exists(output_dirname): + os.makedirs(output_dirname) + with open(output_filename, 'w') as outfile: + print(write_template_to_string(template_filename, **kwargs), file=outfile) + +''' +''' +def gen_llvm_type(type, name, is_pointer, is_pointer_pointer, is_array, is_array_array, array_count, array_count1, is_llvm_struct, is_llvm_enum, is_llvm_pfn, output_file): llvm_type = '' @@ -88,7 +62,7 @@ def gen_llvm_type(type, name, postfix_name, is_pointer, is_pointer_pointer, is_a elif is_llvm_pfn: llvm_type = 'PointerType::get(Type::getInt8Ty(ctx), 0)' else: - if type == "BYTE" or type == "char" or type == "uint8_t" or type == "int8_t" or type == 'bool': + if type == 'BYTE' or type == 'char' or type == 'uint8_t' or type == 'int8_t' or type == 'bool': llvm_type = 'Type::getInt8Ty(ctx)' elif type == 'UINT64' or type == 'INT64' or type == 'uint64_t' or type == 'int64_t': llvm_type = 'Type::getInt64Ty(ctx)' @@ -108,10 +82,22 @@ def gen_llvm_type(type, name, postfix_name, is_pointer, is_pointer_pointer, is_a llvm_type = 'VectorType::get(Type::getFloatTy(ctx), pJitMgr->mVWidth)' elif type == 'simdscalari': llvm_type = 'VectorType::get(Type::getInt32Ty(ctx), pJitMgr->mVWidth)' + elif type == 'SIMD8::vector_t': + llvm_type = 'VectorType::get(Type::getFloatTy(ctx), 8)' + elif type == 'SIMD8::vectori_t': + llvm_type = 'VectorType::get(Type::getInt32Ty(ctx), 8)' + elif type == 'SIMD16::vector_t': + llvm_type = 'VectorType::get(Type::getFloatTy(ctx), 16)' + elif type == 'SIMD16::vectori_t': + llvm_type = 'VectorType::get(Type::getInt32Ty(ctx), 16)' elif type == 'simdvector': llvm_type = 'ArrayType::get(VectorType::get(Type::getFloatTy(ctx), pJitMgr->mVWidth), 4)' + elif type == 'SIMD8::attrib_t': + llvm_type = 'ArrayType::get(VectorType::get(Type::getFloatTy(ctx), 8), 4)' + elif type == 'SIMD16::attrib_t': + llvm_type = 'ArrayType::get(VectorType::get(Type::getFloatTy(ctx), 16), 4)' else: - llvm_type = 'Gen_%s%s(pJitMgr)' % (type, postfix_name) + llvm_type = 'Gen_%s(pJitMgr)' % type if is_pointer: llvm_type = 'PointerType::get(%s, 0)' % llvm_type @@ -124,45 +110,41 @@ def gen_llvm_type(type, name, postfix_name, is_pointer, is_pointer_pointer, is_a elif is_array: llvm_type = 'ArrayType::get(%s, %s)' % (llvm_type, array_count) - return [' members.push_back( %s ); // %s' % (llvm_type, name)] + return { + 'name' : name, + 'type' : llvm_type, + } -""" -""" +''' +''' def gen_llvm_types(input_file, output_file): - output_lines = gen_file_header(os.path.basename(output_file.name)) - lines = input_file.readlines() - postfix_name = "" + types = [] for idx in range(len(lines)): line = lines[idx].rstrip() - if "gen_llvm_types FINI" in line: + if 'gen_llvm_types FINI' in line: break - match = re.match(r"(\s*)struct(\s*)(\w+)", line) + match = re.match(r'(\s*)struct(\s*)(\w+)', line) if match: llvm_args = [] # Detect start of structure - is_fwd_decl = re.search(r";", line) + is_fwd_decl = re.search(r';', line) if not is_fwd_decl: # Extract the command name struct_name = match.group(3).strip() - output_lines += [ - ' //////////////////////////////////////////////////////////////////////////', - ' /// Generate LLVM type information for %s' % struct_name, - ' INLINE static StructType *Gen_%s%s(JitManager* pJitMgr)' % (struct_name, postfix_name), - ' {', - ' LLVMContext& ctx = pJitMgr->mContext;', - ' std::vector members;', - '', - ] + type_entry = { + 'name' : struct_name, + 'members' : [], + } end_of_struct = False @@ -170,7 +152,7 @@ def gen_llvm_types(input_file, output_file): idx += 1 line = lines[idx].rstrip() - is_llvm_typedef = re.search(r"@llvm_typedef", line) + is_llvm_typedef = re.search(r'@llvm_typedef', line) if is_llvm_typedef is not None: is_llvm_typedef = True else: @@ -178,7 +160,7 @@ def gen_llvm_types(input_file, output_file): ########################################### # Is field a llvm struct? Tells script to treat type as array of bytes that is size of structure. - is_llvm_struct = re.search(r"@llvm_struct", line) + is_llvm_struct = re.search(r'@llvm_struct', line) if is_llvm_struct is not None: is_llvm_struct = True @@ -187,7 +169,7 @@ def gen_llvm_types(input_file, output_file): ########################################### # Is field a llvm enum? Tells script to treat type as an enum and replaced with uint32 type. - is_llvm_enum = re.search(r"@llvm_enum", line) + is_llvm_enum = re.search(r'@llvm_enum', line) if is_llvm_enum is not None: is_llvm_enum = True @@ -196,7 +178,7 @@ def gen_llvm_types(input_file, output_file): ########################################### # Is field a llvm function pointer? Tells script to treat type as an enum and replaced with uint32 type. - is_llvm_pfn = re.search(r"@llvm_pfn", line) + is_llvm_pfn = re.search(r'@llvm_pfn', line) if is_llvm_pfn is not None: is_llvm_pfn = True @@ -205,7 +187,7 @@ def gen_llvm_types(input_file, output_file): ########################################### # Is field const? - is_const = re.search(r"\s+const\s+", line) + is_const = re.search(r'\s+const\s+', line) if is_const is not None: is_const = True @@ -214,7 +196,7 @@ def gen_llvm_types(input_file, output_file): ########################################### # Is field a pointer? - is_pointer_pointer = re.search("\*\*", line) + is_pointer_pointer = re.search('\*\*', line) if is_pointer_pointer is not None: is_pointer_pointer = True @@ -223,7 +205,7 @@ def gen_llvm_types(input_file, output_file): ########################################### # Is field a pointer? - is_pointer = re.search("\*", line) + is_pointer = re.search('\*', line) if is_pointer is not None: is_pointer = True @@ -233,7 +215,7 @@ def gen_llvm_types(input_file, output_file): ########################################### # Is field an array of arrays? # TODO: Can add this to a list. - is_array_array = re.search("\[(\w*)\]\[(\w*)\]", line) + is_array_array = re.search('\[(\w*)\]\[(\w*)\]', line) array_count = '0' array_count1 = '0' @@ -246,7 +228,7 @@ def gen_llvm_types(input_file, output_file): ########################################### # Is field an array? - is_array = re.search("\[(\w*)\]", line) + is_array = re.search('\[(\w*)\]', line) if is_array is not None: array_count = is_array.group(1) @@ -254,7 +236,7 @@ def gen_llvm_types(input_file, output_file): else: is_array = False - is_scoped = re.search("::", line) + is_scoped = re.search('::', line) if is_scoped is not None: is_scoped = True @@ -266,37 +248,37 @@ def gen_llvm_types(input_file, output_file): if is_const and is_pointer: if is_scoped: - field_match = re.match(r"(\s*)(\w+\<*\w*\>*)(\s+)(\w+::)(\w+)(\s*\**\s*)(\w+)", line) + field_match = re.match(r'(\s*)(\w+\<*\w*\>*)(\s+)(\w+::)(\w+)(\s*\**\s*)(\w+)', line) - type = "%s%s" % (field_match.group(4), field_match.group(5)) + type = '%s%s' % (field_match.group(4), field_match.group(5)) name = field_match.group(7) else: - field_match = re.match(r"(\s*)(\w+\<*\w*\>*)(\s+)(\w+)(\s*\**\s*)(\w+)", line) + field_match = re.match(r'(\s*)(\w+\<*\w*\>*)(\s+)(\w+)(\s*\**\s*)(\w+)', line) type = field_match.group(4) name = field_match.group(6) elif is_pointer: - field_match = re.match(r"(\s*)(\s+)(\w+\<*\w*\>*)(\s*\**\s*)(\w+)", line) + field_match = re.match(r'(\s*)(\s+)(\w+\<*\w*\>*)(\s*\**\s*)(\w+)', line) if field_match: type = field_match.group(3) name = field_match.group(5) elif is_const: - field_match = re.match(r"(\s*)(\w+\<*\w*\>*)(\s+)(\w+)(\s*)(\w+)", line) + field_match = re.match(r'(\s*)(\w+\<*\w*\>*)(\s+)(\w+)(\s*)(\w+)', line) if field_match: type = field_match.group(4) name = field_match.group(6) else: if is_scoped: - field_match = re.match(r"\s*(\w+\<*\w*\>*)\s*::\s*(\w+\<*\w*\>*)\s+(\w+)", line) + field_match = re.match(r'\s*(\w+\<*\w*\>*)\s*::\s*(\w+\<*\w*\>*)\s+(\w+)', line) if field_match: type = field_match.group(1) + '::' + field_match.group(2) name = field_match.group(3) else: - field_match = re.match(r"(\s*)(\w+\<*\w*\>*)(\s+)(\w+)", line) + field_match = re.match(r'(\s*)(\w+\<*\w*\>*)(\s+)(\w+)', line) if field_match: type = field_match.group(2) @@ -304,42 +286,40 @@ def gen_llvm_types(input_file, output_file): if is_llvm_typedef is False: if type is not None: - output_lines += gen_llvm_type(type, name, postfix_name, is_pointer, is_pointer_pointer, is_array, is_array_array, array_count, array_count1, is_llvm_struct, is_llvm_enum, is_llvm_pfn, output_file) - llvm_args.append(name) + type_entry['members'].append( + gen_llvm_type( + type, name, is_pointer, is_pointer_pointer, is_array, is_array_array, + array_count, array_count1, is_llvm_struct, is_llvm_enum, is_llvm_pfn, output_file)) # Detect end of structure - end_of_struct = re.match(r"(\s*)};", line) - - if (end_of_struct): - output_lines += [ - '', - ' return StructType::get(ctx, members, false);', - ' }', - '', - ] + end_of_struct = re.match(r'(\s*)};', line) - for i in range(len(llvm_args)): - output_lines.append(' static const uint32_t %s%s_%s = %s;' % (struct_name, postfix_name, llvm_args[i], i)) + if end_of_struct: + types.append(type_entry) - output_lines.append('') + cur_dir = os.path.dirname(os.path.abspath(__file__)) + template = os.path.join(cur_dir, 'templates', 'gen_llvm.hpp') - output_lines.append('}') - output_file.write('\n'.join(output_lines) + '\n') + write_template_to_file( + template, + output_file, + cmdline=sys.argv, + filename=os.path.basename(output_file), + types=types) -""" +''' Function which is invoked when this script is started from a command line. Will present and consume a set of arguments which will tell this script how to behave -""" +''' def main(): # Parse args... parser = argparse.ArgumentParser() - parser.add_argument("--input", "-i", type=argparse.FileType('r'), - help="Path to input file containing structs", required=True) - parser.add_argument("--output", "-o", type=argparse.FileType('w'), - help="Path to output file", required=True) - parser.add_argument("--scalar", "-scalar", help="Generates scalar files with all enums", action="store_true", default=False) + parser.add_argument('--input', '-i', type=argparse.FileType('r'), + help='Path to input file containing structs', required=True) + parser.add_argument('--output', '-o', action='store', + help='Path to output file', required=True) args = parser.parse_args() gen_llvm_types(args.input, args.output) diff --git a/src/gallium/drivers/swr/rasterizer/codegen/templates/gen_llvm.hpp b/src/gallium/drivers/swr/rasterizer/codegen/templates/gen_llvm.hpp new file mode 100644 index 00000000000..40bc8a42cdc --- /dev/null +++ b/src/gallium/drivers/swr/rasterizer/codegen/templates/gen_llvm.hpp @@ -0,0 +1,72 @@ +/**************************************************************************** +* Copyright (C) 2014-2017 Intel Corporation. All Rights Reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice (including the next +* paragraph) shall be included in all copies or substantial portions of the +* Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +* IN THE SOFTWARE. +* +* @file ${filename} +* +* @brief auto-generated file +* +* DO NOT EDIT +* +* Generation Command Line: +* ${'\n* '.join(cmdline)} +* +******************************************************************************/ +<%! + def calc_max_len(fields): + max_type_len = 0 + max_name_len = 0 + for f in fields: + if len(f['type']) > max_type_len: max_type_len = len(f['type']) + if len(f['name']) > max_name_len: max_name_len = len(f['name']) + return (max_type_len, max_name_len) + + def pad(cur_len, max_len): + pad_amt = max_len - cur_len + return ' '*pad_amt +%> +#pragma once + +namespace SwrJit +{ + using namespace llvm; + +%for type in types: + INLINE static StructType *Gen_${type['name']}(JitManager* pJitMgr) + { + LLVMContext& ctx = pJitMgr->mContext; + std::vector members; + <% + (max_type_len, max_name_len) = calc_max_len(type['members']) + %> + %for member in type['members']: + /* ${member['name']} ${pad(len(member['name']), max_name_len)} */ members.push_back( ${member['type']} ); + %endfor + + return StructType::get(ctx, members, false); + } + + %for member in type['members']: + static const uint32_t ${type['name']}_${member['name']} ${pad(len(member['name']), max_name_len)}= ${loop.index}; + %endfor + +%endfor +} // ns SwrJit -- 2.30.2