# Copyright (C) 2014-2015 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. #!deps/python32/python.exe 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 * ******************************************************************************/ """ """ """ def gen_file_header(filename): global header headerStr = header % filename return headerStr.splitlines() inst_aliases = { 'SHUFFLE_VECTOR': 'VSHUFFLE', 'INSERT_ELEMENT': 'VINSERT', 'EXTRACT_ELEMENT': 'VEXTRACT', 'MEM_SET': 'MEMSET', 'MEM_CPY': 'MEMCOPY', 'MEM_MOVE': 'MEMMOVE', 'L_SHR': 'LSHR', 'A_SHR': 'ASHR', 'BIT_CAST': 'BITCAST', 'U_DIV': 'UDIV', 'S_DIV': 'SDIV', 'U_REM': 'UREM', 'S_REM': 'SREM', 'BIN_OP': 'BINOP', } intrinsics = [ ["VGATHERPS", "x86_avx2_gather_d_ps_256", ["src", "pBase", "indices", "mask", "scale"]], ["VGATHERDD", "x86_avx2_gather_d_d_256", ["src", "pBase", "indices", "mask", "scale"]], ["VSQRTPS", "x86_avx_sqrt_ps_256", ["a"]], ["VRSQRTPS", "x86_avx_rsqrt_ps_256", ["a"]], ["VRCPPS", "x86_avx_rcp_ps_256", ["a"]], ["VMINPS", "x86_avx_min_ps_256", ["a", "b"]], ["VMAXPS", "x86_avx_max_ps_256", ["a", "b"]], ["VROUND", "x86_avx_round_ps_256", ["a", "rounding"]], ["VCMPPS", "x86_avx_cmp_ps_256", ["a", "b", "cmpop"]], ["VBLENDVPS", "x86_avx_blendv_ps_256", ["a", "b", "mask"]], ["BEXTR_32", "x86_bmi_bextr_32", ["src", "control"]], ["VMASKLOADD", "x86_avx2_maskload_d_256", ["src", "mask"]], ["VMASKMOVPS", "x86_avx_maskload_ps_256", ["src", "mask"]], ["VMASKSTOREPS", "x86_avx_maskstore_ps_256", ["src", "mask", "val"]], ["VPSHUFB", "x86_avx2_pshuf_b", ["a", "b"]], ["VPERMD", "x86_avx2_permd", ["a", "idx"]], ["VPERMPS", "x86_avx2_permps", ["idx", "a"]], ["VCVTPH2PS", "x86_vcvtph2ps_256", ["a"]], ["VCVTPS2PH", "x86_vcvtps2ph_256", ["a", "round"]], ["VHSUBPS", "x86_avx_hsub_ps_256", ["a", "b"]], ["VPTESTC", "x86_avx_ptestc_256", ["a", "b"]], ["VPTESTZ", "x86_avx_ptestz_256", ["a", "b"]], ["VFMADDPS", "x86_fma_vfmadd_ps_256", ["a", "b", "c"]], ["VMOVMSKPS", "x86_avx_movmsk_ps_256", ["a"]], ["INTERRUPT", "x86_int", ["a"]], ] def convert_uppercamel(name): s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).upper() """ Given an input file (e.g. IRBuilder.h) generates function dictionary. """ def parse_ir_builder(input_file): functions = [] lines = input_file.readlines() idx = 0 while idx < len(lines) - 1: line = lines[idx].rstrip() idx += 1 #match = re.search(r"\*Create", line) match = re.search(r"[\*\s]Create(\w*)\(", line) if match is not None: #print("Line: %s" % match.group(1)) if re.search(r"^\s*Create", line) is not None: func_sig = lines[idx-2].rstrip() + line else: func_sig = line end_of_args = False while not end_of_args: end_paren = re.search(r"\)", line) if end_paren is not None: end_of_args = True else: line = lines[idx].rstrip() func_sig += line idx += 1 delfunc = re.search(r"LLVM_DELETED_FUNCTION|= delete;", func_sig) if not delfunc: func = re.search(r"(.*?)\*[\n\s]*(Create\w*)\((.*?)\)", func_sig) if func is not None: return_type = func.group(1).lstrip() + '*' func_name = func.group(2) arguments = func.group(3) func_args = '' func_args_nodefs = '' num_args = arguments.count(',') arg_names = [] num_args = 0 args = arguments.split(',') for arg in args: arg = arg.lstrip() if arg: if num_args > 0: func_args += ', ' func_args_nodefs += ', ' func_args += arg func_args_nodefs += arg.split(' =')[0] split_args = arg.split('=') arg_name = split_args[0].rsplit(None, 1)[-1] #print("Before ArgName = %s" % arg_name) reg_arg = re.search(r"[\&\*]*(\w*)", arg_name) if reg_arg: #print("Arg Name = %s" % reg_arg.group(1)) arg_names += [reg_arg.group(1)] num_args += 1 ignore = False # The following functions need to be ignored. if func_name == 'CreateInsertNUWNSWBinOp': ignore = True if func_name == 'CreateMaskedIntrinsic': ignore = True # Convert CamelCase to CAMEL_CASE func_mod = re.search(r"Create(\w*)", func_name) if func_mod: func_mod = func_mod.group(1) func_mod = convert_uppercamel(func_mod) if func_mod[0:2] == 'F_' or func_mod[0:2] == 'I_': func_mod = func_mod[0] + func_mod[2:] # Substitute alias based on CAMEL_CASE name. func_alias = inst_aliases.get(func_mod) if not func_alias: func_alias = func_mod if func_name == 'CreateCall' or func_name == 'CreateGEP': arglist = re.search(r'ArrayRef', func_args) if arglist: func_alias = func_alias + 'A' if not ignore: functions.append({ "name": func_name, "alias": func_alias, "return": return_type, "args": func_args, "args_nodefs": func_args_nodefs, "arg_names": arg_names }) return functions """ Auto-generates macros for LLVM IR """ def generate_gen_h(functions, output_file): output_lines = gen_file_header(os.path.basename(output_file.name)) output_lines += [ '#pragma once', '', '//////////////////////////////////////////////////////////////////////////', '/// Auto-generated Builder IR declarations', '//////////////////////////////////////////////////////////////////////////', ] for func in functions: name = func['name'] if func['alias']: name = func['alias'] output_lines += [ '%s%s(%s);' % (func['return'], name, func['args']) ] output_file.write('\n'.join(output_lines) + '\n') """ Auto-generates macros for LLVM IR """ def generate_gen_cpp(functions, output_file): output_lines = gen_file_header(os.path.basename(output_file.name)) output_lines += [ '#include \"builder.h\"', '', 'namespace SwrJit', '{', ' using namespace llvm;', '', ] for func in functions: name = func['name'] if func['alias']: name = func['alias'] args = func['arg_names'] func_args = '' first_arg = True for arg in args: if not first_arg: func_args += ', ' func_args += arg first_arg = False output_lines += [ ' //////////////////////////////////////////////////////////////////////////', ' %sBuilder::%s(%s)' % (func['return'], name, func['args_nodefs']), ' {', ' return IRB()->%s(%s);' % (func['name'], func_args), ' }', '', ] output_lines.append('}') output_file.write('\n'.join(output_lines) + '\n') """ Auto-generates macros for LLVM IR """ def generate_x86_h(output_file): output_lines = gen_file_header(os.path.basename(output_file.name)) output_lines += [ '#pragma once', '', '//////////////////////////////////////////////////////////////////////////', '/// Auto-generated x86 intrinsics', '//////////////////////////////////////////////////////////////////////////', ] for inst in intrinsics: #print("Inst: %s, x86: %s numArgs: %d" % (inst[0], inst[1], len(inst[2]))) args = '' first = True for arg in inst[2]: if not first: args += ', ' args += ("Value* %s" % arg) first = False output_lines += [ 'Value *%s(%s);' % (inst[0], args) ] output_file.write('\n'.join(output_lines) + '\n') """ Auto-generates macros for LLVM IR """ def generate_x86_cpp(output_file): output_lines = gen_file_header(os.path.basename(output_file.name)) output_lines += [ '#include \"builder.h\"', '', 'namespace SwrJit', '{', ' using namespace llvm;', '', ] for inst in intrinsics: #print("Inst: %s, x86: %s numArgs: %d" % (inst[0], inst[1], len(inst[2]))) args = '' pass_args = '' first = True for arg in inst[2]: if not first: args += ', ' pass_args += ', ' args += ("Value* %s" % arg) pass_args += arg first = False output_lines += [ ' //////////////////////////////////////////////////////////////////////////', ' Value *Builder::%s(%s)' % (inst[0], args), ' {', ' Function *func = Intrinsic::getDeclaration(JM()->mpCurrentModule, Intrinsic::%s);' % inst[1], ] if inst[0] == "VPERMD": rev_args = '' first = True for arg in reversed(inst[2]): if not first: rev_args += ', ' rev_args += arg first = False output_lines += [ '#if (HAVE_LLVM == 0x306) && (LLVM_VERSION_PATCH == 0)', ' return CALL(func, std::initializer_list{%s});' % rev_args, '#else', ] output_lines += [ ' return CALL(func, std::initializer_list{%s});' % pass_args, ] if inst[0] == "VPERMD": output_lines += [ '#endif', ] output_lines += [ ' }', '', ] output_lines.append('}') output_file.write('\n'.join(output_lines) + '\n') """ 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 IRBuilder.h", required=False) parser.add_argument("--output", "-o", type=argparse.FileType('w'), help="Path to output file", required=True) parser.add_argument("--gen_h", "-gen_h", help="Generate builder_gen.h", action="store_true", default=False) parser.add_argument("--gen_cpp", "-gen_cpp", help="Generate builder_gen.cpp", action="store_true", default=False) parser.add_argument("--gen_x86_h", "-gen_x86_h", help="Generate x86 intrinsics. No input is needed.", action="store_true", default=False) parser.add_argument("--gen_x86_cpp", "-gen_x86_cpp", help="Generate x86 intrinsics. No input is needed.", action="store_true", default=False) args = parser.parse_args() if args.input: functions = parse_ir_builder(args.input) if args.gen_h: generate_gen_h(functions, args.output) if args.gen_cpp: generate_gen_cpp(functions, args.output) else: if args.gen_x86_h: generate_x86_h(args.output) if args.gen_x86_cpp: generate_x86_cpp(args.output) if args.gen_h: print("Need to specify --input for --gen_h!") if args.gen_cpp: print("Need to specify --input for --gen_cpp!") if __name__ == '__main__': main() # END OF FILE