1 # Copyright (C) 2014-2018 Intel Corporation. All Rights Reserved.
3 # Permission is hereby granted, free of charge, to any person obtaining a
4 # copy of this software and associated documentation files (the "Software"),
5 # to deal in the Software without restriction, including without limitation
6 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 # and/or sell copies of the Software, and to permit persons to whom the
8 # Software is furnished to do so, subject to the following conditions:
10 # The above copyright notice and this permission notice (including the next
11 # paragraph) shall be included in all copies or substantial portions of the
14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 from __future__
import print_function
24 from gen_common
import *
25 from argparse
import FileType
29 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
):
34 if is_pointer
or is_pointer_pointer
:
35 llvm_type
= 'Type::getInt32Ty(ctx)'
37 llvm_type
= 'ArrayType::get(Type::getInt8Ty(ctx), sizeof(%s))' % type
39 llvm_type
= 'Type::getInt32Ty(ctx)'
41 llvm_type
= 'PointerType::get(Type::getInt8Ty(ctx), 0)'
43 if type == 'BYTE' or type == 'char' or type == 'uint8_t' or type == 'int8_t' or type == 'bool':
44 llvm_type
= 'Type::getInt8Ty(ctx)'
45 elif type == 'UINT64' or type == 'INT64' or type == 'uint64_t' or type == 'int64_t' or type == 'gfxptr_t':
46 llvm_type
= 'Type::getInt64Ty(ctx)'
47 elif type == 'UINT16' or type == 'int16_t' or type == 'uint16_t':
48 llvm_type
= 'Type::getInt16Ty(ctx)'
49 elif type == 'UINT' or type == 'INT' or type == 'int' or type == 'BOOL' or type == 'uint32_t' or type == 'int32_t':
50 llvm_type
= 'Type::getInt32Ty(ctx)'
51 elif type == 'float' or type == 'FLOAT':
52 llvm_type
= 'Type::getFloatTy(ctx)'
53 elif type == 'double' or type == 'DOUBLE':
54 llvm_type
= 'Type::getDoubleTy(ctx)'
55 elif type == 'void' or type == 'VOID':
56 llvm_type
= 'Type::getInt32Ty(ctx)'
57 elif type == 'HANDLE':
58 llvm_type
= 'PointerType::get(Type::getInt32Ty(ctx), 0)'
59 elif type == 'simdscalar':
60 llvm_type
= 'getVectorType(Type::getFloatTy(ctx), pJitMgr->mVWidth)'
61 elif type == 'simdscalari':
62 llvm_type
= 'getVectorType(Type::getInt32Ty(ctx), pJitMgr->mVWidth)'
63 elif type == 'simd16scalar':
64 llvm_type
= 'getVectorType(Type::getFloatTy(ctx), 16)'
65 elif type == 'simd16scalari':
66 llvm_type
= 'getVectorType(Type::getInt32Ty(ctx), 16)'
67 elif type == '__m128i':
68 llvm_type
= 'getVectorType(Type::getInt32Ty(ctx), 4)'
69 elif type == 'SIMD256::Float':
70 llvm_type
= 'getVectorType(Type::getFloatTy(ctx), 8)'
71 elif type == 'SIMD256::Integer':
72 llvm_type
= 'getVectorType(Type::getInt32Ty(ctx), 8)'
73 elif type == 'SIMD512::Float':
74 llvm_type
= 'getVectorType(Type::getFloatTy(ctx), 16)'
75 elif type == 'SIMD512::Integer':
76 llvm_type
= 'getVectorType(Type::getInt32Ty(ctx), 16)'
77 elif type == 'simdvector':
78 llvm_type
= 'ArrayType::get(getVectorType(Type::getFloatTy(ctx), 8), 4)'
79 elif type == 'simd16vector':
80 llvm_type
= 'ArrayType::get(getVectorType(Type::getFloatTy(ctx), 16), 4)'
81 elif type == 'SIMD256::Vec4':
82 llvm_type
= 'ArrayType::get(getVectorType(Type::getFloatTy(ctx), 8), 4)'
83 elif type == 'SIMD512::Vec4':
84 llvm_type
= 'ArrayType::get(getVectorType(Type::getFloatTy(ctx), 16), 4)'
86 llvm_type
= 'Gen_%s(pJitMgr)' % type
89 llvm_type
= 'PointerType::get(%s, 0)' % llvm_type
91 if is_pointer_pointer
:
92 llvm_type
= 'PointerType::get(%s, 0)' % llvm_type
95 llvm_type
= 'ArrayType::get(ArrayType::get(%s, %s), %s)' % (llvm_type
, array_count1
, array_count
)
97 llvm_type
= 'ArrayType::get(%s, %s)' % (llvm_type
, array_count
)
107 def gen_llvm_types(input_file
, output_file
):
109 lines
= input_file
.readlines()
113 for idx
in range(len(lines
)):
114 line
= lines
[idx
].rstrip()
116 if 'gen_llvm_types FINI' in line
:
119 match
= re
.match(r
'(\s*)struct(\s*)(\w+)', line
)
123 # Detect start of structure
124 is_fwd_decl
= re
.search(r
';', line
)
128 # Extract the command name
129 struct_name
= match
.group(3).strip()
132 'name' : struct_name
,
137 end_of_struct
= False
139 while not end_of_struct
and idx
< len(lines
)-1:
141 line
= lines
[idx
].rstrip()
143 is_llvm_typedef
= re
.search(r
'@llvm_typedef', line
)
144 if is_llvm_typedef
is not None:
145 is_llvm_typedef
= True
148 is_llvm_typedef
= False
150 ###########################################
151 # Is field a llvm struct? Tells script to treat type as array of bytes that is size of structure.
152 is_llvm_struct
= re
.search(r
'@llvm_struct', line
)
154 if is_llvm_struct
is not None:
155 is_llvm_struct
= True
157 is_llvm_struct
= False
159 ###########################################
160 # Is field the start of a function? Tells script to ignore it
161 is_llvm_func_start
= re
.search(r
'@llvm_func_start', line
)
163 if is_llvm_func_start
is not None:
164 while not end_of_struct
and idx
< len(lines
)-1:
166 line
= lines
[idx
].rstrip()
167 is_llvm_func_end
= re
.search(r
'@llvm_func_end', line
)
168 if is_llvm_func_end
is not None:
172 ###########################################
173 # Is field a function? Tells script to ignore it
174 is_llvm_func
= re
.search(r
'@llvm_func', line
)
176 if is_llvm_func
is not None:
179 ###########################################
180 # Is field a llvm enum? Tells script to treat type as an enum and replaced with uint32 type.
181 is_llvm_enum
= re
.search(r
'@llvm_enum', line
)
183 if is_llvm_enum
is not None:
188 ###########################################
189 # Is field a llvm function pointer? Tells script to treat type as an enum and replaced with uint32 type.
190 is_llvm_pfn
= re
.search(r
'@llvm_pfn', line
)
192 if is_llvm_pfn
is not None:
197 ###########################################
199 is_const
= re
.search(r
'\s+const\s+', line
)
201 if is_const
is not None:
206 ###########################################
207 # Is field a pointer?
208 is_pointer_pointer
= re
.search('\*\*', line
)
210 if is_pointer_pointer
is not None:
211 is_pointer_pointer
= True
213 is_pointer_pointer
= False
215 ###########################################
216 # Is field a pointer?
217 is_pointer
= re
.search('\*', line
)
219 if is_pointer
is not None:
224 ###########################################
225 # Is field an array of arrays?
226 # TODO: Can add this to a list.
227 is_array_array
= re
.search('\[(\w*)\]\[(\w*)\]', line
)
231 if is_array_array
is not None:
232 array_count
= is_array_array
.group(1)
233 array_count1
= is_array_array
.group(2)
234 is_array_array
= True
236 is_array_array
= False
238 ###########################################
240 is_array
= re
.search('\[(\w*)\]', line
)
242 if is_array
is not None:
243 array_count
= is_array
.group(1)
248 is_scoped
= re
.search('::', line
)
250 if is_scoped
is not None:
257 if is_const
and is_pointer
:
260 field_match
= re
.match(r
'(\s*)(\w+\<*\w*\>*)(\s+)(\w+::)(\w+)(\s*\**\s*)(\w+)', line
)
262 type = '%s%s' % (field_match
.group(4), field_match
.group(5))
263 name
= field_match
.group(7)
265 field_match
= re
.match(r
'(\s*)(\w+\<*\w*\>*)(\s+)(\w+)(\s*\**\s*)(\w+)', line
)
267 type = field_match
.group(4)
268 name
= field_match
.group(6)
271 field_match
= re
.match(r
'(\s*)(\s+)(\w+\<*\w*\>*)(\s*\**\s*)(\w+)', line
)
274 type = field_match
.group(3)
275 name
= field_match
.group(5)
277 field_match
= re
.match(r
'(\s*)(\w+\<*\w*\>*)(\s+)(\w+)(\s*)(\w+)', line
)
280 type = field_match
.group(4)
281 name
= field_match
.group(6)
284 field_match
= re
.match(r
'\s*(\w+\<*\w*\>*)\s*::\s*(\w+\<*\w*\>*)\s+(\w+)', line
)
287 type = field_match
.group(1) + '::' + field_match
.group(2)
288 name
= field_match
.group(3)
290 field_match
= re
.match(r
'(\s*)(\w+\<*\w*\>*)(\s+)(\w+)', line
)
293 type = field_match
.group(2)
294 name
= field_match
.group(4)
296 if is_llvm_typedef
is False:
298 type_entry
['members'].append(
300 type, name
, idx
+1, is_pointer
, is_pointer_pointer
, is_array
, is_array_array
,
301 array_count
, array_count1
, is_llvm_struct
, is_llvm_enum
, is_llvm_pfn
, output_file
))
303 # Detect end of structure
304 end_of_struct
= re
.match(r
'(\s*)};', line
)
307 types
.append(type_entry
)
309 cur_dir
= os
.path
.dirname(os
.path
.abspath(__file__
))
310 template
= os
.path
.join(cur_dir
, 'templates', 'gen_llvm.hpp')
312 MakoTemplateWriter
.to_file(
316 filename
=os
.path
.basename(output_file
),
318 input_dir
=os
.path
.dirname(input_file
.name
),
319 input_file
=os
.path
.basename(input_file
.name
))
322 Function which is invoked when this script is started from a command line.
323 Will present and consume a set of arguments which will tell this script how
329 parser
= ArgumentParser()
330 parser
.add_argument('--input', '-i', type=FileType('r'),
331 help='Path to input file containing structs', required
=True)
332 parser
.add_argument('--output', '-o', action
='store',
333 help='Path to output file', required
=True)
334 args
= parser
.parse_args()
336 final_output_dir
= os
.path
.dirname(args
.output
)
337 if MakeDir(final_output_dir
):
340 final_output_file
= args
.output
342 tmp_dir
= MakeTmpDir('_codegen')
343 args
.output
= os
.path
.join(tmp_dir
, os
.path
.basename(args
.output
))
347 gen_llvm_types(args
.input, args
.output
)
349 rval
= CopyFileIfDifferent(args
.output
, final_output_file
)
351 print('ERROR: Could not generate llvm types', file=sys
.stderr
)
355 DeleteDirTree(tmp_dir
)
359 if __name__
== '__main__':