blob: 78762ef8760434d5fcbfac1853fc6300f55f8176 [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é Fonseca2f2ea482011-10-15 15:10:06 +010056 print ' %s = (%s).to%s();' % (lvalue, rvalue, literal.kind)
José Fonsecae0e61402010-11-25 15:03:23 +000057
58 def visit_const(self, const, lvalue, rvalue):
59 self.visit(const.type, lvalue, rvalue)
60
61 def visit_alias(self, alias, lvalue, rvalue):
62 self.visit(alias.type, lvalue, rvalue)
63
64 def visit_enum(self, enum, lvalue, rvalue):
José Fonseca56e093c2011-05-07 01:09:19 +010065 print ' %s = (%s).toSInt();' % (lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +000066
67 def visit_bitmask(self, bitmask, lvalue, rvalue):
68 self.visit(bitmask.type, lvalue, rvalue)
69
70 def visit_array(self, array, lvalue, rvalue):
José Fonsecab4a3d142011-10-27 07:43:19 +010071 print ' const trace::Array *__a%s = dynamic_cast<const trace::Array *>(&%s);' % (array.tag, rvalue)
José Fonseca02c25002011-10-15 13:17:26 +010072 print ' if (__a%s) {' % (array.tag)
73 length = '__a%s->values.size()' % array.tag
José Fonsecae7c7d642011-10-05 08:05:26 +010074 print ' %s = new %s[%s];' % (lvalue, array.type, length)
José Fonseca02c25002011-10-15 13:17:26 +010075 index = '__j' + array.tag
José Fonsecadbaae492011-04-21 09:28:10 +010076 print ' for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
José Fonsecae0e61402010-11-25 15:03:23 +000077 try:
José Fonseca02c25002011-10-15 13:17:26 +010078 self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.tag, index))
José Fonsecae0e61402010-11-25 15:03:23 +000079 finally:
80 print ' }'
81 print ' } else {'
82 print ' %s = NULL;' % lvalue
83 print ' }'
84
85 def visit_pointer(self, pointer, lvalue, rvalue):
José Fonsecab4a3d142011-10-27 07:43:19 +010086 print ' const trace::Array *__a%s = dynamic_cast<const trace::Array *>(&%s);' % (pointer.tag, rvalue)
José Fonseca02c25002011-10-15 13:17:26 +010087 print ' if (__a%s) {' % (pointer.tag)
José Fonsecae7c7d642011-10-05 08:05:26 +010088 print ' %s = new %s;' % (lvalue, pointer.type)
José Fonsecae0e61402010-11-25 15:03:23 +000089 try:
José Fonseca02c25002011-10-15 13:17:26 +010090 self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.tag,))
José Fonsecae0e61402010-11-25 15:03:23 +000091 finally:
92 print ' } else {'
93 print ' %s = NULL;' % lvalue
94 print ' }'
95
96 def visit_handle(self, handle, lvalue, rvalue):
José Fonsecaa10af892011-04-11 09:10:55 +010097 OpaqueValueExtractor().visit(handle.type, lvalue, rvalue);
98 new_lvalue = handle_entry(handle, lvalue)
José Fonseca031b7382011-05-10 20:36:40 +010099 print ' if (retrace::verbosity >= 2) {'
José Fonsecaa10af892011-04-11 09:10:55 +0100100 print ' std::cout << "%s " << size_t(%s) << " <- " << size_t(%s) << "\\n";' % (handle.name, lvalue, new_lvalue)
José Fonseca031b7382011-05-10 20:36:40 +0100101 print ' }'
José Fonsecaa10af892011-04-11 09:10:55 +0100102 print ' %s = %s;' % (lvalue, new_lvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000103
104 def visit_blob(self, blob, lvalue, rvalue):
José Fonseca7ebb9e22011-05-06 09:58:45 +0100105 print ' %s = static_cast<%s>((%s).toPointer());' % (lvalue, blob, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000106
107 def visit_string(self, string, lvalue, rvalue):
José Fonseca7ebb9e22011-05-06 09:58:45 +0100108 print ' %s = (%s)((%s).toString());' % (lvalue, string.expr, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000109
110
José Fonsecaa10af892011-04-11 09:10:55 +0100111class OpaqueValueExtractor(ValueExtractor):
112 '''Value extractor that also understands opaque values.
113
114 Normally opaque values can't be retraced, unless they are being extracted
115 in the context of handles.'''
116
117 def visit_opaque(self, opaque, lvalue, rvalue):
José Fonseca46a48392011-10-14 11:34:27 +0100118 print ' %s = static_cast<%s>(retrace::toPointer(%s));' % (lvalue, opaque, rvalue)
José Fonsecaa10af892011-04-11 09:10:55 +0100119
José Fonsecae0e61402010-11-25 15:03:23 +0000120
121class ValueWrapper(stdapi.Visitor):
122
123 def visit_literal(self, literal, lvalue, rvalue):
124 pass
125
126 def visit_alias(self, alias, lvalue, rvalue):
127 self.visit(alias.type, lvalue, rvalue)
128
129 def visit_enum(self, enum, lvalue, rvalue):
130 pass
131
132 def visit_bitmask(self, bitmask, lvalue, rvalue):
133 pass
134
135 def visit_array(self, array, lvalue, rvalue):
José Fonsecab4a3d142011-10-27 07:43:19 +0100136 print ' const trace::Array *__a%s = dynamic_cast<const trace::Array *>(&%s);' % (array.tag, rvalue)
José Fonseca02c25002011-10-15 13:17:26 +0100137 print ' if (__a%s) {' % (array.tag)
138 length = '__a%s->values.size()' % array.tag
139 index = '__j' + array.tag
José Fonsecadbaae492011-04-21 09:28:10 +0100140 print ' for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
José Fonsecae0e61402010-11-25 15:03:23 +0000141 try:
José Fonseca02c25002011-10-15 13:17:26 +0100142 self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.tag, index))
José Fonsecae0e61402010-11-25 15:03:23 +0000143 finally:
144 print ' }'
145 print ' }'
146
147 def visit_pointer(self, pointer, lvalue, rvalue):
José Fonsecab4a3d142011-10-27 07:43:19 +0100148 print ' const trace::Array *__a%s = dynamic_cast<const trace::Array *>(&%s);' % (pointer.tag, rvalue)
José Fonseca02c25002011-10-15 13:17:26 +0100149 print ' if (__a%s) {' % (pointer.tag)
José Fonsecae0e61402010-11-25 15:03:23 +0000150 try:
José Fonseca02c25002011-10-15 13:17:26 +0100151 self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.tag,))
José Fonsecae0e61402010-11-25 15:03:23 +0000152 finally:
153 print ' }'
154
José Fonsecae0e61402010-11-25 15:03:23 +0000155 def visit_handle(self, handle, lvalue, rvalue):
José Fonsecaa10af892011-04-11 09:10:55 +0100156 print ' %s __orig_result;' % handle.type
157 OpaqueValueExtractor().visit(handle.type, '__orig_result', rvalue);
José Fonsecad922e1d2010-11-25 17:14:02 +0000158 if handle.range is None:
José Fonsecaa10af892011-04-11 09:10:55 +0100159 rvalue = "__orig_result"
José Fonseca8a844ae2010-12-06 18:50:52 +0000160 entry = handle_entry(handle, rvalue)
161 print " %s = %s;" % (entry, lvalue)
José Fonseca031b7382011-05-10 20:36:40 +0100162 print ' if (retrace::verbosity >= 2) {'
José Fonseca8a844ae2010-12-06 18:50:52 +0000163 print ' std::cout << "{handle.name} " << {rvalue} << " -> " << {lvalue} << "\\n";'.format(**locals())
José Fonseca031b7382011-05-10 20:36:40 +0100164 print ' }'
José Fonsecad922e1d2010-11-25 17:14:02 +0000165 else:
José Fonseca02c25002011-10-15 13:17:26 +0100166 i = '__h' + handle.tag
José Fonseca8a844ae2010-12-06 18:50:52 +0000167 lvalue = "%s + %s" % (lvalue, i)
José Fonsecaa10af892011-04-11 09:10:55 +0100168 rvalue = "__orig_result + %s" % (i,)
José Fonseca8a844ae2010-12-06 18:50:52 +0000169 entry = handle_entry(handle, rvalue)
José Fonsecadbaae492011-04-21 09:28:10 +0100170 print ' for ({handle.type} {i} = 0; {i} < {handle.range}; ++{i}) {{'.format(**locals())
José Fonseca8a844ae2010-12-06 18:50:52 +0000171 print ' {entry} = {lvalue};'.format(**locals())
José Fonseca031b7382011-05-10 20:36:40 +0100172 print ' if (retrace::verbosity >= 2) {'
José Fonseca8a844ae2010-12-06 18:50:52 +0000173 print ' std::cout << "{handle.name} " << ({rvalue}) << " -> " << ({lvalue}) << "\\n";'.format(**locals())
José Fonseca031b7382011-05-10 20:36:40 +0100174 print ' }'
José Fonsecad922e1d2010-11-25 17:14:02 +0000175 print ' }'
José Fonsecae0e61402010-11-25 15:03:23 +0000176
177 def visit_blob(self, blob, lvalue, rvalue):
178 pass
179
180 def visit_string(self, string, lvalue, rvalue):
181 pass
182
183
José Fonsecae0e61402010-11-25 15:03:23 +0000184class Retracer:
185
186 def retrace_function(self, function):
José Fonsecab4a3d142011-10-27 07:43:19 +0100187 print 'static void retrace_%s(trace::Call &call) {' % function.name
José Fonseca62212972011-03-23 13:22:55 +0000188 self.retrace_function_body(function)
189 print '}'
190 print
191
192 def retrace_function_body(self, function):
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100193 if not function.sideeffects:
José Fonseca9109c3a2011-05-24 19:31:26 +0100194 print ' (void)call;'
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100195 return
196
José Fonsecae0e61402010-11-25 15:03:23 +0000197 success = True
198 for arg in function.args:
199 arg_type = ConstRemover().visit(arg.type)
200 #print ' // %s -> %s' % (arg.type, arg_type)
201 print ' %s %s;' % (arg_type, arg.name)
202 rvalue = 'call.arg(%u)' % (arg.index,)
203 lvalue = arg.name
204 try:
José Fonsecadacd8dd2010-11-25 17:50:26 +0000205 self.extract_arg(function, arg, arg_type, lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000206 except NotImplementedError:
207 success = False
208 print ' %s = 0; // FIXME' % arg.name
209 if not success:
José Fonseca9109c3a2011-05-24 19:31:26 +0100210 print ' if (1) {'
José Fonsecafa15d332010-11-25 20:22:39 +0000211 self.fail_function(function)
José Fonseca9109c3a2011-05-24 19:31:26 +0100212 print ' }'
José Fonsecafa15d332010-11-25 20:22:39 +0000213 self.call_function(function)
José Fonsecae0e61402010-11-25 15:03:23 +0000214 for arg in function.args:
215 if arg.output:
216 arg_type = ConstRemover().visit(arg.type)
217 rvalue = 'call.arg(%u)' % (arg.index,)
218 lvalue = arg.name
219 try:
220 ValueWrapper().visit(arg_type, lvalue, rvalue)
221 except NotImplementedError:
José Fonseca0a37edf2011-10-09 09:45:22 +0100222 print ' // XXX: %s' % arg.name
José Fonsecae0e61402010-11-25 15:03:23 +0000223 if function.type is not stdapi.Void:
224 rvalue = '*call.ret'
225 lvalue = '__result'
226 try:
227 ValueWrapper().visit(function.type, lvalue, rvalue)
228 except NotImplementedError:
José Fonseca46a48392011-10-14 11:34:27 +0100229 print ' // XXX: result'
José Fonseca0a37edf2011-10-09 09:45:22 +0100230 if not success:
231 if function.name[-1].islower():
José Fonsecaf5cda412011-10-09 17:27:23 +0100232 sys.stderr.write('warning: unsupported %s call\n' % function.name)
José Fonsecae0e61402010-11-25 15:03:23 +0000233
José Fonsecafa15d332010-11-25 20:22:39 +0000234 def fail_function(self, function):
José Fonsecab1bb3c22011-10-08 20:23:18 +0100235 print ' if (retrace::verbosity >= 0) {'
José Fonsecaf5cda412011-10-09 17:27:23 +0100236 print ' retrace::unsupported(call);'
José Fonsecab1bb3c22011-10-08 20:23:18 +0100237 print ' }'
José Fonsecafa15d332010-11-25 20:22:39 +0000238 print ' return;'
239
José Fonsecadacd8dd2010-11-25 17:50:26 +0000240 def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
241 ValueExtractor().visit(arg_type, lvalue, rvalue)
José Fonsecafd34e4e2011-06-03 19:34:29 +0100242
243 def extract_opaque_arg(self, function, arg, arg_type, lvalue, rvalue):
244 OpaqueValueExtractor().visit(arg_type, lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000245
José Fonsecafa15d332010-11-25 20:22:39 +0000246 def call_function(self, function):
247 arg_names = ", ".join([arg.name for arg in function.args])
248 if function.type is not stdapi.Void:
249 print ' %s __result;' % (function.type)
250 print ' __result = %s(%s);' % (function.name, arg_names)
José Fonseca974a3fb2011-05-23 21:15:12 +0100251 print ' (void)__result;'
José Fonsecafa15d332010-11-25 20:22:39 +0000252 else:
253 print ' %s(%s);' % (function.name, arg_names)
254
José Fonseca4441baf2010-11-25 19:55:27 +0000255 def filter_function(self, function):
256 return True
257
José Fonseca2741ed82011-10-07 23:36:39 +0100258 table_name = 'retrace::callbacks'
259
José Fonsecae0e61402010-11-25 15:03:23 +0000260 def retrace_functions(self, functions):
José Fonseca4441baf2010-11-25 19:55:27 +0000261 functions = filter(self.filter_function, functions)
262
José Fonsecae0e61402010-11-25 15:03:23 +0000263 for function in functions:
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100264 self.retrace_function(function)
José Fonsecae0e61402010-11-25 15:03:23 +0000265
José Fonseca2741ed82011-10-07 23:36:39 +0100266 print 'const retrace::Entry %s[] = {' % self.table_name
267 for function in functions:
268 print ' {"%s", &retrace_%s},' % (function.name, function.name)
269 print ' {NULL, NULL}'
270 print '};'
José Fonsecae0e61402010-11-25 15:03:23 +0000271 print
272
273
274 def retrace_api(self, api):
275
276 print '#include "trace_parser.hpp"'
José Fonseca91343f52011-04-01 08:37:06 +0100277 print '#include "retrace.hpp"'
José Fonsecae0e61402010-11-25 15:03:23 +0000278 print
279
280 types = api.all_types()
281 handles = [type for type in types if isinstance(type, stdapi.Handle)]
José Fonsecad922e1d2010-11-25 17:14:02 +0000282 handle_names = set()
José Fonsecae0e61402010-11-25 15:03:23 +0000283 for handle in handles:
José Fonsecad922e1d2010-11-25 17:14:02 +0000284 if handle.name not in handle_names:
José Fonseca8a844ae2010-12-06 18:50:52 +0000285 if handle.key is None:
José Fonseca91343f52011-04-01 08:37:06 +0100286 print 'static retrace::map<%s> __%s_map;' % (handle.type, handle.name)
José Fonseca8a844ae2010-12-06 18:50:52 +0000287 else:
288 key_name, key_type = handle.key
José Fonseca91343f52011-04-01 08:37:06 +0100289 print 'static std::map<%s, retrace::map<%s> > __%s_map;' % (key_type, handle.type, handle.name)
José Fonsecad922e1d2010-11-25 17:14:02 +0000290 handle_names.add(handle.name)
José Fonsecae0e61402010-11-25 15:03:23 +0000291 print
292
José Fonsecae0e61402010-11-25 15:03:23 +0000293 self.retrace_functions(api.functions)
294