swr: [rasterizer codegen] Rewrite gen_llvm_types.py to use mako
authorTim Rowley <timothy.o.rowley@intel.com>
Wed, 15 Mar 2017 18:37:50 +0000 (13:37 -0500)
committerTim Rowley <timothy.o.rowley@intel.com>
Mon, 20 Mar 2017 23:05:54 +0000 (18:05 -0500)
Reviewed-by: Bruce Cherniak <bruce.cherniak@intel.com>
src/gallium/drivers/swr/Makefile.am
src/gallium/drivers/swr/SConscript
src/gallium/drivers/swr/rasterizer/codegen/gen_llvm_types.py
src/gallium/drivers/swr/rasterizer/codegen/templates/gen_llvm.hpp [new file with mode: 0644]

index 771f1a8243953c3795e7c329c696151670ff9589..99a7df5f6c4f09c1239cd0c7b74664903350a27d 100644 (file)
@@ -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
index 754e6784f2e4971d77ebe0507c01bfff88f9f6ce..efcc686aaa709b09f7ad06e9fec285dd1b2aa19b 100644 (file)
@@ -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'
index e88158c14d879018573e88818fa6e270a80d0a5a..72e67978d9fc2ddb9ce8fc01827c34845a69c3f4 100644 (file)
@@ -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"),
 # 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<Type*> 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 (file)
index 0000000..40bc8a4
--- /dev/null
@@ -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<Type*> 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