blob: 8650220c086c89a8211151eabc09b095ca989a3b [file] [log] [blame]
# 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.
from __future__ import print_function
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 = 'VectorType::get(Type::getFloatTy(ctx), pJitMgr->mVWidth)'
elif type == 'simdscalari':
llvm_type = 'VectorType::get(Type::getInt32Ty(ctx), pJitMgr->mVWidth)'
elif type == 'simd16scalar':
llvm_type = 'VectorType::get(Type::getFloatTy(ctx), 16)'
elif type == 'simd16scalari':
llvm_type = 'VectorType::get(Type::getInt32Ty(ctx), 16)'
elif type == '__m128i':
llvm_type = 'VectorType::get(Type::getInt32Ty(ctx), 4)'
elif type == 'SIMD256::Float':
llvm_type = 'VectorType::get(Type::getFloatTy(ctx), 8)'
elif type == 'SIMD256::Integer':
llvm_type = 'VectorType::get(Type::getInt32Ty(ctx), 8)'
elif type == 'SIMD512::Float':
llvm_type = 'VectorType::get(Type::getFloatTy(ctx), 16)'
elif type == 'SIMD512::Integer':
llvm_type = 'VectorType::get(Type::getInt32Ty(ctx), 16)'
elif type == 'simdvector':
llvm_type = 'ArrayType::get(VectorType::get(Type::getFloatTy(ctx), 8), 4)'
elif type == 'simd16vector':
llvm_type = 'ArrayType::get(VectorType::get(Type::getFloatTy(ctx), 16), 4)'
elif type == 'SIMD256::Vec4':
llvm_type = 'ArrayType::get(VectorType::get(Type::getFloatTy(ctx), 8), 4)'
elif type == 'SIMD512::Vec4':
llvm_type = 'ArrayType::get(VectorType::get(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