# Copyright (C) 2014-2018 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. import os, sys, re from gen_common import * from argparse import FileType ''' ''' def gen_llvm_type(type, name, idx, 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 = '' if is_llvm_struct: if is_pointer or is_pointer_pointer: llvm_type = 'Type::getInt32Ty(ctx)' else: llvm_type = 'ArrayType::get(Type::getInt8Ty(ctx), sizeof(%s))' % type elif is_llvm_enum: llvm_type = 'Type::getInt32Ty(ctx)' 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': llvm_type = 'Type::getInt8Ty(ctx)' elif type == 'UINT64' or type == 'INT64' or type == 'uint64_t' or type == 'int64_t' or type == 'gfxptr_t': llvm_type = 'Type::getInt64Ty(ctx)' elif type == 'UINT16' or type == 'int16_t' or type == 'uint16_t': llvm_type = 'Type::getInt16Ty(ctx)' elif type == 'UINT' or type == 'INT' or type == 'int' or type == 'BOOL' or type == 'uint32_t' or type == 'int32_t': llvm_type = 'Type::getInt32Ty(ctx)' elif type == 'float' or type == 'FLOAT': llvm_type = 'Type::getFloatTy(ctx)' elif type == 'double' or type == 'DOUBLE': llvm_type = 'Type::getDoubleTy(ctx)' elif type == 'void' or type == 'VOID': llvm_type = 'Type::getInt32Ty(ctx)' elif type == 'HANDLE': llvm_type = 'PointerType::get(Type::getInt32Ty(ctx), 0)' elif type == 'simdscalar': llvm_type = 'getVectorType(Type::getFloatTy(ctx), pJitMgr->mVWidth)' elif type == 'simdscalari': llvm_type = 'getVectorType(Type::getInt32Ty(ctx), pJitMgr->mVWidth)' elif type == 'simd16scalar': llvm_type = 'getVectorType(Type::getFloatTy(ctx), 16)' elif type == 'simd16scalari': llvm_type = 'getVectorType(Type::getInt32Ty(ctx), 16)' elif type == '__m128i': llvm_type = 'getVectorType(Type::getInt32Ty(ctx), 4)' elif type == 'SIMD256::Float': llvm_type = 'getVectorType(Type::getFloatTy(ctx), 8)' elif type == 'SIMD256::Integer': llvm_type = 'getVectorType(Type::getInt32Ty(ctx), 8)' elif type == 'SIMD512::Float': llvm_type = 'getVectorType(Type::getFloatTy(ctx), 16)' elif type == 'SIMD512::Integer': llvm_type = 'getVectorType(Type::getInt32Ty(ctx), 16)' elif type == 'simdvector': llvm_type = 'ArrayType::get(getVectorType(Type::getFloatTy(ctx), 8), 4)' elif type == 'simd16vector': llvm_type = 'ArrayType::get(getVectorType(Type::getFloatTy(ctx), 16), 4)' elif type == 'SIMD256::Vec4': llvm_type = 'ArrayType::get(getVectorType(Type::getFloatTy(ctx), 8), 4)' elif type == 'SIMD512::Vec4': llvm_type = 'ArrayType::get(getVectorType(Type::getFloatTy(ctx), 16), 4)' else: llvm_type = 'Gen_%s(pJitMgr)' % type if is_pointer: llvm_type = 'PointerType::get(%s, 0)' % llvm_type if is_pointer_pointer: llvm_type = 'PointerType::get(%s, 0)' % llvm_type if is_array_array: llvm_type = 'ArrayType::get(ArrayType::get(%s, %s), %s)' % (llvm_type, array_count1, array_count) elif is_array: llvm_type = 'ArrayType::get(%s, %s)' % (llvm_type, array_count) return { 'name' : name, 'lineNum' : idx, 'type' : llvm_type, } ''' ''' def gen_llvm_types(input_file, output_file): lines = input_file.readlines() types = [] for idx in range(len(lines)): line = lines[idx].rstrip() if 'gen_llvm_types FINI' in line: break match = re.match(r'(\s*)struct(\s*)(\w+)', line) if match: llvm_args = [] # Detect start of structure is_fwd_decl = re.search(r';', line) if not is_fwd_decl: # Extract the command name struct_name = match.group(3).strip() type_entry = { 'name' : struct_name, 'lineNum' : idx+1, 'members' : [], } end_of_struct = False while not end_of_struct and idx < len(lines)-1: idx += 1 line = lines[idx].rstrip() is_llvm_typedef = re.search(r'@llvm_typedef', line) if is_llvm_typedef is not None: is_llvm_typedef = True continue else: is_llvm_typedef = False ########################################### # 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) if is_llvm_struct is not None: is_llvm_struct = True else: is_llvm_struct = False ########################################### # Is field the start of a function? Tells script to ignore it is_llvm_func_start = re.search(r'@llvm_func_start', line) if is_llvm_func_start is not None: while not end_of_struct and idx < len(lines)-1: idx += 1 line = lines[idx].rstrip() is_llvm_func_end = re.search(r'@llvm_func_end', line) if is_llvm_func_end is not None: break; continue ########################################### # Is field a function? Tells script to ignore it is_llvm_func = re.search(r'@llvm_func', line) if is_llvm_func is not None: continue ########################################### # 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) if is_llvm_enum is not None: is_llvm_enum = True else: is_llvm_enum = False ########################################### # 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) if is_llvm_pfn is not None: is_llvm_pfn = True else: is_llvm_pfn = False ########################################### # Is field const? is_const = re.search(r'\s+const\s+', line) if is_const is not None: is_const = True else: is_const = False ########################################### # Is field a pointer? is_pointer_pointer = re.search('\*\*', line) if is_pointer_pointer is not None: is_pointer_pointer = True else: is_pointer_pointer = False ########################################### # Is field a pointer? is_pointer = re.search('\*', line) if is_pointer is not None: is_pointer = True else: is_pointer = False ########################################### # Is field an array of arrays? # TODO: Can add this to a list. is_array_array = re.search('\[(\w*)\]\[(\w*)\]', line) array_count = '0' array_count1 = '0' if is_array_array is not None: array_count = is_array_array.group(1) array_count1 = is_array_array.group(2) is_array_array = True else: is_array_array = False ########################################### # Is field an array? is_array = re.search('\[(\w*)\]', line) if is_array is not None: array_count = is_array.group(1) is_array = True else: is_array = False is_scoped = re.search('::', line) if is_scoped is not None: is_scoped = True else: is_scoped = False type = None name = None if is_const and is_pointer: if is_scoped: 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)) name = field_match.group(7) else: 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) 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) 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) 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) if field_match: type = field_match.group(2) name = field_match.group(4) if is_llvm_typedef is False: if type is not None: type_entry['members'].append( gen_llvm_type( type, name, idx+1, 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: types.append(type_entry) cur_dir = os.path.dirname(os.path.abspath(__file__)) template = os.path.join(cur_dir, 'templates', 'gen_llvm.hpp') MakoTemplateWriter.to_file( template, output_file, cmdline=sys.argv, filename=os.path.basename(output_file), types=types, input_dir=os.path.dirname(input_file.name), input_file=os.path.basename(input_file.name)) ''' 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 = ArgumentParser() parser.add_argument('--input', '-i', type=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() final_output_dir = os.path.dirname(args.output) if MakeDir(final_output_dir): return 1 final_output_file = args.output tmp_dir = MakeTmpDir('_codegen') args.output = os.path.join(tmp_dir, os.path.basename(args.output)) rval = 0 try: gen_llvm_types(args.input, args.output) rval = CopyFileIfDifferent(args.output, final_output_file) except: print('ERROR: Could not generate llvm types', file=sys.stderr) rval = 1 finally: DeleteDirTree(tmp_dir) return rval if __name__ == '__main__': sys.exit(main()) # END OF FILE