blob: 4425ad1e99fbd697c854cebfeda1f777a47ef386 [file] [log] [blame]
José Fonsecae0e61402010-11-25 15:03:23 +00001##########################################################################
2#
3# Copyright 2010 VMware, Inc.
4# All Rights Reserved.
5#
6# Permission is hereby granted, free of charge, to any person obtaining a copy
7# of this software and associated documentation files (the "Software"), to deal
8# in the Software without restriction, including without limitation the rights
9# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10# copies of the Software, and to permit persons to whom the Software is
11# furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice shall be included in
14# all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22# THE SOFTWARE.
23#
24##########################################################################/
25
26
José Fonseca4a826ed2010-11-30 16:58:22 +000027"""Generic retracing code generator."""
28
José Fonseca0a37edf2011-10-09 09:45:22 +010029
30import sys
31
José Fonsecabd86a222011-09-27 09:21:38 +010032import specs.stdapi as stdapi
33import specs.glapi as glapi
José Fonsecae0e61402010-11-25 15:03:23 +000034
35
36class ConstRemover(stdapi.Rebuilder):
37
38 def visit_const(self, const):
39 return const.type
40
41 def visit_opaque(self, opaque):
José Fonsecaf01b7f52011-04-20 21:09:28 +010042 return opaque
José Fonsecae0e61402010-11-25 15:03:23 +000043
44
José Fonseca8a844ae2010-12-06 18:50:52 +000045def handle_entry(handle, value):
46 if handle.key is None:
47 return "__%s_map[%s]" % (handle.name, value)
48 else:
49 key_name, key_type = handle.key
50 return "__%s_map[%s][%s]" % (handle.name, key_name, value)
51
52
José Fonsecae0e61402010-11-25 15:03:23 +000053class ValueExtractor(stdapi.Visitor):
54
55 def visit_literal(self, literal, lvalue, rvalue):
José Fonseca56e093c2011-05-07 01:09:19 +010056 #if literal.format in ('Bool', 'UInt'):
57 print ' %s = (%s).to%s();' % (lvalue, rvalue, literal.format)
José Fonsecae0e61402010-11-25 15:03:23 +000058
59 def visit_const(self, const, lvalue, rvalue):
60 self.visit(const.type, lvalue, rvalue)
61
62 def visit_alias(self, alias, lvalue, rvalue):
63 self.visit(alias.type, lvalue, rvalue)
64
65 def visit_enum(self, enum, lvalue, rvalue):
José Fonseca56e093c2011-05-07 01:09:19 +010066 print ' %s = (%s).toSInt();' % (lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +000067
68 def visit_bitmask(self, bitmask, lvalue, rvalue):
69 self.visit(bitmask.type, lvalue, rvalue)
70
71 def visit_array(self, array, lvalue, rvalue):
72 print ' const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (array.id, rvalue)
73 print ' if (__a%s) {' % (array.id)
74 length = '__a%s->values.size()' % array.id
José Fonsecae7c7d642011-10-05 08:05:26 +010075 print ' %s = new %s[%s];' % (lvalue, array.type, length)
José Fonsecae0e61402010-11-25 15:03:23 +000076 index = '__j' + array.id
José Fonsecadbaae492011-04-21 09:28:10 +010077 print ' for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
José Fonsecae0e61402010-11-25 15:03:23 +000078 try:
79 self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.id, index))
80 finally:
81 print ' }'
82 print ' } else {'
83 print ' %s = NULL;' % lvalue
84 print ' }'
85
86 def visit_pointer(self, pointer, lvalue, rvalue):
87 print ' const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (pointer.id, rvalue)
88 print ' if (__a%s) {' % (pointer.id)
José Fonsecae7c7d642011-10-05 08:05:26 +010089 print ' %s = new %s;' % (lvalue, pointer.type)
José Fonsecae0e61402010-11-25 15:03:23 +000090 try:
91 self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.id,))
92 finally:
93 print ' } else {'
94 print ' %s = NULL;' % lvalue
95 print ' }'
96
97 def visit_handle(self, handle, lvalue, rvalue):
José Fonsecaa10af892011-04-11 09:10:55 +010098 OpaqueValueExtractor().visit(handle.type, lvalue, rvalue);
99 new_lvalue = handle_entry(handle, lvalue)
José Fonseca031b7382011-05-10 20:36:40 +0100100 print ' if (retrace::verbosity >= 2) {'
José Fonsecaa10af892011-04-11 09:10:55 +0100101 print ' std::cout << "%s " << size_t(%s) << " <- " << size_t(%s) << "\\n";' % (handle.name, lvalue, new_lvalue)
José Fonseca031b7382011-05-10 20:36:40 +0100102 print ' }'
José Fonsecaa10af892011-04-11 09:10:55 +0100103 print ' %s = %s;' % (lvalue, new_lvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000104
105 def visit_blob(self, blob, lvalue, rvalue):
José Fonseca7ebb9e22011-05-06 09:58:45 +0100106 print ' %s = static_cast<%s>((%s).toPointer());' % (lvalue, blob, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000107
108 def visit_string(self, string, lvalue, rvalue):
José Fonseca7ebb9e22011-05-06 09:58:45 +0100109 print ' %s = (%s)((%s).toString());' % (lvalue, string.expr, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000110
111
José Fonsecaa10af892011-04-11 09:10:55 +0100112class OpaqueValueExtractor(ValueExtractor):
113 '''Value extractor that also understands opaque values.
114
115 Normally opaque values can't be retraced, unless they are being extracted
116 in the context of handles.'''
117
118 def visit_opaque(self, opaque, lvalue, rvalue):
José Fonseca7ebb9e22011-05-06 09:58:45 +0100119 print ' %s = static_cast<%s>((%s).toPointer());' % (lvalue, opaque, rvalue)
José Fonsecaa10af892011-04-11 09:10:55 +0100120
José Fonsecae0e61402010-11-25 15:03:23 +0000121
122class ValueWrapper(stdapi.Visitor):
123
124 def visit_literal(self, literal, lvalue, rvalue):
125 pass
126
127 def visit_alias(self, alias, lvalue, rvalue):
128 self.visit(alias.type, lvalue, rvalue)
129
130 def visit_enum(self, enum, lvalue, rvalue):
131 pass
132
133 def visit_bitmask(self, bitmask, lvalue, rvalue):
134 pass
135
136 def visit_array(self, array, lvalue, rvalue):
137 print ' const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (array.id, rvalue)
138 print ' if (__a%s) {' % (array.id)
139 length = '__a%s->values.size()' % array.id
140 index = '__j' + array.id
José Fonsecadbaae492011-04-21 09:28:10 +0100141 print ' for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
José Fonsecae0e61402010-11-25 15:03:23 +0000142 try:
143 self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.id, index))
144 finally:
145 print ' }'
146 print ' }'
147
148 def visit_pointer(self, pointer, lvalue, rvalue):
149 print ' const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (pointer.id, rvalue)
150 print ' if (__a%s) {' % (pointer.id)
151 try:
152 self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.id,))
153 finally:
154 print ' }'
155
José Fonsecae0e61402010-11-25 15:03:23 +0000156 def visit_handle(self, handle, lvalue, rvalue):
José Fonsecaa10af892011-04-11 09:10:55 +0100157 print ' %s __orig_result;' % handle.type
158 OpaqueValueExtractor().visit(handle.type, '__orig_result', rvalue);
José Fonsecad922e1d2010-11-25 17:14:02 +0000159 if handle.range is None:
José Fonsecaa10af892011-04-11 09:10:55 +0100160 rvalue = "__orig_result"
José Fonseca8a844ae2010-12-06 18:50:52 +0000161 entry = handle_entry(handle, rvalue)
162 print " %s = %s;" % (entry, lvalue)
José Fonseca031b7382011-05-10 20:36:40 +0100163 print ' if (retrace::verbosity >= 2) {'
José Fonseca8a844ae2010-12-06 18:50:52 +0000164 print ' std::cout << "{handle.name} " << {rvalue} << " -> " << {lvalue} << "\\n";'.format(**locals())
José Fonseca031b7382011-05-10 20:36:40 +0100165 print ' }'
José Fonsecad922e1d2010-11-25 17:14:02 +0000166 else:
167 i = '__h' + handle.id
José Fonseca8a844ae2010-12-06 18:50:52 +0000168 lvalue = "%s + %s" % (lvalue, i)
José Fonsecaa10af892011-04-11 09:10:55 +0100169 rvalue = "__orig_result + %s" % (i,)
José Fonseca8a844ae2010-12-06 18:50:52 +0000170 entry = handle_entry(handle, rvalue)
José Fonsecadbaae492011-04-21 09:28:10 +0100171 print ' for ({handle.type} {i} = 0; {i} < {handle.range}; ++{i}) {{'.format(**locals())
José Fonseca8a844ae2010-12-06 18:50:52 +0000172 print ' {entry} = {lvalue};'.format(**locals())
José Fonseca031b7382011-05-10 20:36:40 +0100173 print ' if (retrace::verbosity >= 2) {'
José Fonseca8a844ae2010-12-06 18:50:52 +0000174 print ' std::cout << "{handle.name} " << ({rvalue}) << " -> " << ({lvalue}) << "\\n";'.format(**locals())
José Fonseca031b7382011-05-10 20:36:40 +0100175 print ' }'
José Fonsecad922e1d2010-11-25 17:14:02 +0000176 print ' }'
José Fonsecae0e61402010-11-25 15:03:23 +0000177
178 def visit_blob(self, blob, lvalue, rvalue):
179 pass
180
181 def visit_string(self, string, lvalue, rvalue):
182 pass
183
184
José Fonsecae0e61402010-11-25 15:03:23 +0000185class Retracer:
186
187 def retrace_function(self, function):
188 print 'static void retrace_%s(Trace::Call &call) {' % function.name
José Fonseca62212972011-03-23 13:22:55 +0000189 self.retrace_function_body(function)
190 print '}'
191 print
192
193 def retrace_function_body(self, function):
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100194 if not function.sideeffects:
José Fonseca9109c3a2011-05-24 19:31:26 +0100195 print ' (void)call;'
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100196 return
197
José Fonsecae0e61402010-11-25 15:03:23 +0000198 success = True
199 for arg in function.args:
200 arg_type = ConstRemover().visit(arg.type)
201 #print ' // %s -> %s' % (arg.type, arg_type)
202 print ' %s %s;' % (arg_type, arg.name)
203 rvalue = 'call.arg(%u)' % (arg.index,)
204 lvalue = arg.name
205 try:
José Fonsecadacd8dd2010-11-25 17:50:26 +0000206 self.extract_arg(function, arg, arg_type, lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000207 except NotImplementedError:
208 success = False
209 print ' %s = 0; // FIXME' % arg.name
210 if not success:
José Fonseca9109c3a2011-05-24 19:31:26 +0100211 print ' if (1) {'
José Fonsecafa15d332010-11-25 20:22:39 +0000212 self.fail_function(function)
José Fonseca9109c3a2011-05-24 19:31:26 +0100213 print ' }'
José Fonsecafa15d332010-11-25 20:22:39 +0000214 self.call_function(function)
José Fonsecae0e61402010-11-25 15:03:23 +0000215 for arg in function.args:
216 if arg.output:
217 arg_type = ConstRemover().visit(arg.type)
218 rvalue = 'call.arg(%u)' % (arg.index,)
219 lvalue = arg.name
220 try:
221 ValueWrapper().visit(arg_type, lvalue, rvalue)
222 except NotImplementedError:
José Fonseca0a37edf2011-10-09 09:45:22 +0100223 print ' // XXX: %s' % arg.name
José Fonsecae0e61402010-11-25 15:03:23 +0000224 if function.type is not stdapi.Void:
225 rvalue = '*call.ret'
226 lvalue = '__result'
227 try:
228 ValueWrapper().visit(function.type, lvalue, rvalue)
229 except NotImplementedError:
José Fonseca0a37edf2011-10-09 09:45:22 +0100230 success = False
231 print ' // FIXME: result'
232 if not success:
233 if function.name[-1].islower():
234 sys.stderr.write('warning: %s unsupported\n' % function.name)
José Fonsecae0e61402010-11-25 15:03:23 +0000235
José Fonsecafa15d332010-11-25 20:22:39 +0000236 def fail_function(self, function):
José Fonsecab1bb3c22011-10-08 20:23:18 +0100237 print ' if (retrace::verbosity >= 0) {'
238 print ' retrace::unknown(call);'
239 print ' }'
José Fonsecafa15d332010-11-25 20:22:39 +0000240 print ' return;'
241
José Fonsecadacd8dd2010-11-25 17:50:26 +0000242 def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
243 ValueExtractor().visit(arg_type, lvalue, rvalue)
José Fonsecafd34e4e2011-06-03 19:34:29 +0100244
245 def extract_opaque_arg(self, function, arg, arg_type, lvalue, rvalue):
246 OpaqueValueExtractor().visit(arg_type, lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000247
José Fonsecafa15d332010-11-25 20:22:39 +0000248 def call_function(self, function):
249 arg_names = ", ".join([arg.name for arg in function.args])
250 if function.type is not stdapi.Void:
251 print ' %s __result;' % (function.type)
252 print ' __result = %s(%s);' % (function.name, arg_names)
José Fonseca974a3fb2011-05-23 21:15:12 +0100253 print ' (void)__result;'
José Fonsecafa15d332010-11-25 20:22:39 +0000254 else:
255 print ' %s(%s);' % (function.name, arg_names)
256
José Fonseca4441baf2010-11-25 19:55:27 +0000257 def filter_function(self, function):
258 return True
259
José Fonseca2741ed82011-10-07 23:36:39 +0100260 table_name = 'retrace::callbacks'
261
José Fonsecae0e61402010-11-25 15:03:23 +0000262 def retrace_functions(self, functions):
José Fonseca4441baf2010-11-25 19:55:27 +0000263 functions = filter(self.filter_function, functions)
264
José Fonsecae0e61402010-11-25 15:03:23 +0000265 for function in functions:
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100266 self.retrace_function(function)
José Fonsecae0e61402010-11-25 15:03:23 +0000267
José Fonseca2741ed82011-10-07 23:36:39 +0100268 print 'const retrace::Entry %s[] = {' % self.table_name
269 for function in functions:
270 print ' {"%s", &retrace_%s},' % (function.name, function.name)
271 print ' {NULL, NULL}'
272 print '};'
José Fonsecae0e61402010-11-25 15:03:23 +0000273 print
274
275
276 def retrace_api(self, api):
277
278 print '#include "trace_parser.hpp"'
José Fonseca91343f52011-04-01 08:37:06 +0100279 print '#include "retrace.hpp"'
José Fonsecae0e61402010-11-25 15:03:23 +0000280 print
281
282 types = api.all_types()
283 handles = [type for type in types if isinstance(type, stdapi.Handle)]
José Fonsecad922e1d2010-11-25 17:14:02 +0000284 handle_names = set()
José Fonsecae0e61402010-11-25 15:03:23 +0000285 for handle in handles:
José Fonsecad922e1d2010-11-25 17:14:02 +0000286 if handle.name not in handle_names:
José Fonseca8a844ae2010-12-06 18:50:52 +0000287 if handle.key is None:
José Fonseca91343f52011-04-01 08:37:06 +0100288 print 'static retrace::map<%s> __%s_map;' % (handle.type, handle.name)
José Fonseca8a844ae2010-12-06 18:50:52 +0000289 else:
290 key_name, key_type = handle.key
José Fonseca91343f52011-04-01 08:37:06 +0100291 print 'static std::map<%s, retrace::map<%s> > __%s_map;' % (key_type, handle.type, handle.name)
José Fonsecad922e1d2010-11-25 17:14:02 +0000292 handle_names.add(handle.name)
José Fonsecae0e61402010-11-25 15:03:23 +0000293 print
294
José Fonsecae0e61402010-11-25 15:03:23 +0000295 self.retrace_functions(api.functions)
296