blob: 90a44140f27dc1d3e3f8f9b4780c40dfc052d6ef [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é Fonseca46a48392011-10-14 11:34:27 +0100119 print ' %s = static_cast<%s>(retrace::toPointer(%s));' % (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é Fonseca46a48392011-10-14 11:34:27 +0100230 print ' // XXX: result'
José Fonseca0a37edf2011-10-09 09:45:22 +0100231 if not success:
232 if function.name[-1].islower():
José Fonsecaf5cda412011-10-09 17:27:23 +0100233 sys.stderr.write('warning: unsupported %s call\n' % function.name)
José Fonsecae0e61402010-11-25 15:03:23 +0000234
José Fonsecafa15d332010-11-25 20:22:39 +0000235 def fail_function(self, function):
José Fonsecab1bb3c22011-10-08 20:23:18 +0100236 print ' if (retrace::verbosity >= 0) {'
José Fonsecaf5cda412011-10-09 17:27:23 +0100237 print ' retrace::unsupported(call);'
José Fonsecab1bb3c22011-10-08 20:23:18 +0100238 print ' }'
José Fonsecafa15d332010-11-25 20:22:39 +0000239 print ' return;'
240
José Fonsecadacd8dd2010-11-25 17:50:26 +0000241 def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
242 ValueExtractor().visit(arg_type, lvalue, rvalue)
José Fonsecafd34e4e2011-06-03 19:34:29 +0100243
244 def extract_opaque_arg(self, function, arg, arg_type, lvalue, rvalue):
245 OpaqueValueExtractor().visit(arg_type, lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000246
José Fonsecafa15d332010-11-25 20:22:39 +0000247 def call_function(self, function):
248 arg_names = ", ".join([arg.name for arg in function.args])
249 if function.type is not stdapi.Void:
250 print ' %s __result;' % (function.type)
251 print ' __result = %s(%s);' % (function.name, arg_names)
José Fonseca974a3fb2011-05-23 21:15:12 +0100252 print ' (void)__result;'
José Fonsecafa15d332010-11-25 20:22:39 +0000253 else:
254 print ' %s(%s);' % (function.name, arg_names)
255
José Fonseca4441baf2010-11-25 19:55:27 +0000256 def filter_function(self, function):
257 return True
258
José Fonseca2741ed82011-10-07 23:36:39 +0100259 table_name = 'retrace::callbacks'
260
José Fonsecae0e61402010-11-25 15:03:23 +0000261 def retrace_functions(self, functions):
José Fonseca4441baf2010-11-25 19:55:27 +0000262 functions = filter(self.filter_function, functions)
263
José Fonsecae0e61402010-11-25 15:03:23 +0000264 for function in functions:
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100265 self.retrace_function(function)
José Fonsecae0e61402010-11-25 15:03:23 +0000266
José Fonseca2741ed82011-10-07 23:36:39 +0100267 print 'const retrace::Entry %s[] = {' % self.table_name
268 for function in functions:
269 print ' {"%s", &retrace_%s},' % (function.name, function.name)
270 print ' {NULL, NULL}'
271 print '};'
José Fonsecae0e61402010-11-25 15:03:23 +0000272 print
273
274
275 def retrace_api(self, api):
276
277 print '#include "trace_parser.hpp"'
José Fonseca91343f52011-04-01 08:37:06 +0100278 print '#include "retrace.hpp"'
José Fonsecae0e61402010-11-25 15:03:23 +0000279 print
280
281 types = api.all_types()
282 handles = [type for type in types if isinstance(type, stdapi.Handle)]
José Fonsecad922e1d2010-11-25 17:14:02 +0000283 handle_names = set()
José Fonsecae0e61402010-11-25 15:03:23 +0000284 for handle in handles:
José Fonsecad922e1d2010-11-25 17:14:02 +0000285 if handle.name not in handle_names:
José Fonseca8a844ae2010-12-06 18:50:52 +0000286 if handle.key is None:
José Fonseca91343f52011-04-01 08:37:06 +0100287 print 'static retrace::map<%s> __%s_map;' % (handle.type, handle.name)
José Fonseca8a844ae2010-12-06 18:50:52 +0000288 else:
289 key_name, key_type = handle.key
José Fonseca91343f52011-04-01 08:37:06 +0100290 print 'static std::map<%s, retrace::map<%s> > __%s_map;' % (key_type, handle.type, handle.name)
José Fonsecad922e1d2010-11-25 17:14:02 +0000291 handle_names.add(handle.name)
José Fonsecae0e61402010-11-25 15:03:23 +0000292 print
293
José Fonsecae0e61402010-11-25 15:03:23 +0000294 self.retrace_functions(api.functions)
295