gallium/swr: Fix vcvtph2ps llvm intrinsic compile error
[mesa.git] / src / gallium / drivers / swr / rasterizer / codegen / gen_archrast.py
1 # Copyright (C) 2014-2016 Intel Corporation. All Rights Reserved.
2 #
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:
9 #
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
12 # Software.
13 #
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
20 # IN THE SOFTWARE.
21
22 # Python source
23 from __future__ import print_function
24 import os
25 import sys
26 import re
27 from gen_common import *
28
29 def parse_event_fields(lines, idx, event_dict):
30 """
31 Parses lines from a proto file that contain an event definition and stores it in event_dict
32 """
33 fields = []
34 end_of_event = False
35
36 # record all fields in event definition.
37 # note: we don't check if there's a leading brace.
38 while not end_of_event and idx < len(lines):
39 line = lines[idx].rstrip()
40 idx += 1
41
42 # ex 1: uint32_t numSampleCLZExecuted; // number of sample_cl_z instructions executed
43 # ex 2: char reason[256]; // size of reason
44 match = re.match(r'^(\s*)([\w\*]+)(\s+)([\w]+)(\[\d+\])*;\s*(\/\/.*)*$', line)
45 # group 1 -
46 # group 2 type
47 # group 3 -
48 # group 4 name
49 # group 5 [array size]
50 # group 6 //comment
51
52 if match:
53 field = {
54 "type": match.group(2),
55 "name": match.group(4),
56 "size": int(match.group(5)[1:-1]) if match.group(5) else 1,
57 "desc": match.group(6)[2:].strip() if match.group(6) else "",
58 }
59 fields.append(field)
60
61 end_of_event = re.match(r'(\s*)};', line)
62
63 event_dict['fields'] = fields
64 event_dict['num_fields'] = len(fields)
65
66 return idx
67
68 def parse_enums(lines, idx, event_dict):
69 """
70 Parses lines from a proto file that contain an enum definition and stores it in event_dict
71 """
72 enum_names = []
73 end_of_enum = False
74
75 # record all enum values in enumeration
76 # note: we don't check if there's a leading brace.
77 while not end_of_enum and idx < len(lines):
78 line = lines[idx].rstrip()
79 idx += 1
80
81 preprocessor = re.search(r'#if|#endif', line)
82
83 if not preprocessor:
84 enum = re.match(r'(\s*)(\w+)(\s*)', line)
85
86 if enum:
87 enum_names.append(line)
88
89 end_of_enum = re.match(r'(\s*)};', line)
90
91 event_dict['names'] = enum_names
92 return idx
93
94 def parse_protos(files, verbose=False):
95 """
96 Parses a proto file and returns a dictionary of event definitions
97 """
98
99 # Protos structure:
100 #
101 # {
102 # "events": {
103 # "defs": { // dict of event definitions where keys are 'group_name::event_name"
104 # ...,
105 # "ApiStat::DrawInfoEvent": {
106 # "id": 3,
107 # "group": "ApiStat",
108 # "name": "DrawInfoEvent", // name of event without 'group_name::' prefix
109 # "desc": "",
110 # "fields": [
111 # {
112 # "type": "uint32_t",
113 # "name": "drawId",
114 # "size": 1,
115 # "desc": "",
116 # },
117 # ...
118 # ]
119 # },
120 # ...
121 # },
122 # "groups": { // dict of groups with lists of event keys
123 # "ApiStat": [
124 # "ApiStat::DispatchEvent",
125 # "ApiStat::DrawInfoEvent",
126 # ...
127 # ],
128 # "Framework": [
129 # "Framework::ThreadStartApiEvent",
130 # "Framework::ThreadStartWorkerEvent",
131 # ...
132 # ],
133 # ...
134 # },
135 # "map": { // map of event ids to match archrast output to event key
136 # "1": "Framework::ThreadStartApiEvent",
137 # "2": "Framework::ThreadStartWorkerEvent",
138 # "3": "ApiStat::DrawInfoEvent",
139 # ...
140 # }
141 # },
142 # "enums": { ... } // enums follow similar defs, map (groups?) structure
143 # }
144
145 protos = {
146 'events': {
147 'defs': {}, # event dictionary containing events with their fields
148 'map': {}, # dictionary to map event ids to event names
149 'groups': {} # event keys stored by groups
150 },
151 'enums': {
152 'defs': {},
153 'map': {}
154 }
155 }
156
157 event_id = 0
158 enum_id = 0
159
160 if type(files) is not list:
161 files = [files]
162
163 for filename in files:
164 if verbose:
165 print("Parsing proto file: %s" % os.path.normpath(filename))
166
167 with open(filename, 'r') as f:
168 lines = f.readlines()
169 in_brief = False
170 brief = []
171 idx = 0
172 while idx < len(lines):
173 line = lines[idx].strip()
174 idx += 1
175
176 # If currently processing a brief, keep processing or change state
177 if in_brief:
178 match = re.match(r'^\s*\/\/\/\s*(.*)$', line) # i.e. "/// more event desc..."
179 if match:
180 brief.append(match.group(1).strip())
181 continue
182 else:
183 in_brief = False
184
185 # Match event/enum brief
186 match = re.match(r'^\s*\/\/\/\s*@(brief|breif)\s*(.*)$', line) # i.e. "///@brief My event desc..."
187 if match:
188 in_brief = True
189 brief.append(match.group(2).strip())
190 continue
191
192 # Match event definition
193 match = re.match(r'event(\s*)(((\w*)::){0,1}(\w+))', line) # i.e. "event SWTag::CounterEvent"
194 if match:
195 event_id += 1
196
197 # Parse event attributes
198 event_key = match.group(2) # i.e. SWTag::CounterEvent
199 event_group = match.group(4) if match.group(4) else "" # i.e. SWTag
200 event_name = match.group(5) # i.e. CounterEvent
201
202 # Define event attributes
203 event = {
204 'id': event_id,
205 'group': event_group,
206 'name': event_name,
207 'desc': ' '.join(brief)
208 }
209 # Add period at end of event desc if necessary
210 if event["desc"] and event["desc"][-1] != '.':
211 event["desc"] += '.'
212
213 # Reset brief
214 brief = []
215
216 # Now add event fields
217 idx = parse_event_fields(lines, idx, event)
218
219 # Register event and mapping
220 protos['events']['defs'][event_key] = event
221 protos['events']['map'][event_id] = event_key
222
223 continue
224
225 # Match enum definition
226 match = re.match(r'enum(\s*)(\w+)', line)
227 if match:
228 enum_id += 1
229
230 # Parse enum attributes
231 enum_name = match.group(2)
232
233 # Define enum attr
234 enum = {
235 'name': enum_name,
236 'desc': ' '.join(brief)
237 }
238 # Add period at end of event desc if necessary
239 if enum["desc"] and enum["desc"][-1] != '.':
240 enum["desc"] += '.'
241
242 # Reset brief
243 brief = []
244
245 # Now add enum fields
246 idx = parse_enums(lines, idx, enum)
247
248 # Register enum and mapping
249 protos['enums']['defs'][enum_name] = enum
250 protos['enums']['map'][enum_id] = enum_name
251
252 continue
253
254 # Sort and group events
255 event_groups = protos['events']['groups']
256 for key in sorted(protos['events']['defs']):
257 group = protos['events']['defs'][key]['group']
258 if group not in event_groups:
259 event_groups[group] = []
260 event_groups[group].append(key)
261
262 return protos
263
264
265 def main():
266
267 # Parse args...
268 parser = ArgumentParser()
269 parser.add_argument("--proto", "-p", dest="protos", nargs='+', help="Path to all proto file(s) to process. Accepts one or more paths (i.e. events.proto and events_private.proto)", required=True)
270 parser.add_argument("--output-dir", help="Output dir (defaults to ./codegen). Will create folder if it does not exist.", required=False, default="codegen")
271 parser.add_argument("--verbose", "-v", help="Verbose", action="store_true")
272 args = parser.parse_args()
273
274 if not os.path.exists(args.output_dir):
275 MakeDir(args.output_dir)
276
277 for f in args.protos:
278 if not os.path.exists(f):
279 print('Error: Could not find proto file %s' % f, file=sys.stderr)
280 return 1
281
282 # Parse each proto file and add to protos container
283 protos = parse_protos(args.protos, args.verbose)
284
285 files = [
286 ["gen_ar_event.hpp", ""],
287 ["gen_ar_event.cpp", ""],
288 ["gen_ar_eventhandler.hpp", "gen_ar_event.hpp"],
289 ["gen_ar_eventhandlerfile.hpp", "gen_ar_eventhandler.hpp"]
290 ]
291
292 rval = 0
293
294 try:
295 # Delete existing files
296 for f in files:
297 filename = f[0]
298 output_fullpath = os.path.join(args.output_dir, filename)
299 if os.path.exists(output_fullpath):
300 if args.verbose:
301 print("Deleting existing file: %s" % output_fullpath)
302 os.remove(output_fullpath)
303
304 # Generate files from templates
305 print("Generating c++ from proto files...")
306 for f in files:
307 filename = f[0]
308 event_header = f[1]
309 curdir = os.path.dirname(os.path.abspath(__file__))
310 template_file = os.path.join(curdir, 'templates', filename)
311 output_fullpath = os.path.join(args.output_dir, filename)
312
313 if args.verbose:
314 print("Generating: %s" % output_fullpath)
315 MakoTemplateWriter.to_file(template_file, output_fullpath,
316 cmdline=sys.argv,
317 filename=filename,
318 protos=protos,
319 event_header=event_header)
320
321 except Exception as e:
322 print(e)
323 rval = 1
324
325 return rval
326
327 if __name__ == '__main__':
328 sys.exit(main())