blob: 9092f351366a2377231761c962e2c1daec382879 [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é Fonsecabd86a222011-09-27 09:21:38 +010029import specs.stdapi as stdapi
30import specs.glapi as glapi
José Fonsecae0e61402010-11-25 15:03:23 +000031
32
33class ConstRemover(stdapi.Rebuilder):
34
35 def visit_const(self, const):
36 return const.type
37
38 def visit_opaque(self, opaque):
José Fonsecaf01b7f52011-04-20 21:09:28 +010039 return opaque
José Fonsecae0e61402010-11-25 15:03:23 +000040
41
José Fonseca8a844ae2010-12-06 18:50:52 +000042def handle_entry(handle, value):
43 if handle.key is None:
44 return "__%s_map[%s]" % (handle.name, value)
45 else:
46 key_name, key_type = handle.key
47 return "__%s_map[%s][%s]" % (handle.name, key_name, value)
48
49
José Fonsecae0e61402010-11-25 15:03:23 +000050class ValueExtractor(stdapi.Visitor):
51
52 def visit_literal(self, literal, lvalue, rvalue):
José Fonseca56e093c2011-05-07 01:09:19 +010053 #if literal.format in ('Bool', 'UInt'):
54 print ' %s = (%s).to%s();' % (lvalue, rvalue, literal.format)
José Fonsecae0e61402010-11-25 15:03:23 +000055
56 def visit_const(self, const, lvalue, rvalue):
57 self.visit(const.type, lvalue, rvalue)
58
59 def visit_alias(self, alias, lvalue, rvalue):
60 self.visit(alias.type, lvalue, rvalue)
61
62 def visit_enum(self, enum, lvalue, rvalue):
José Fonseca56e093c2011-05-07 01:09:19 +010063 print ' %s = (%s).toSInt();' % (lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +000064
65 def visit_bitmask(self, bitmask, lvalue, rvalue):
66 self.visit(bitmask.type, lvalue, rvalue)
67
68 def visit_array(self, array, lvalue, rvalue):
69 print ' const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (array.id, rvalue)
70 print ' if (__a%s) {' % (array.id)
71 length = '__a%s->values.size()' % array.id
José Fonsecae7c7d642011-10-05 08:05:26 +010072 print ' %s = new %s[%s];' % (lvalue, array.type, length)
José Fonsecae0e61402010-11-25 15:03:23 +000073 index = '__j' + array.id
José Fonsecadbaae492011-04-21 09:28:10 +010074 print ' for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
José Fonsecae0e61402010-11-25 15:03:23 +000075 try:
76 self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.id, index))
77 finally:
78 print ' }'
79 print ' } else {'
80 print ' %s = NULL;' % lvalue
81 print ' }'
82
83 def visit_pointer(self, pointer, lvalue, rvalue):
84 print ' const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (pointer.id, rvalue)
85 print ' if (__a%s) {' % (pointer.id)
José Fonsecae7c7d642011-10-05 08:05:26 +010086 print ' %s = new %s;' % (lvalue, pointer.type)
José Fonsecae0e61402010-11-25 15:03:23 +000087 try:
88 self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.id,))
89 finally:
90 print ' } else {'
91 print ' %s = NULL;' % lvalue
92 print ' }'
93
94 def visit_handle(self, handle, lvalue, rvalue):
José Fonsecaa10af892011-04-11 09:10:55 +010095 OpaqueValueExtractor().visit(handle.type, lvalue, rvalue);
96 new_lvalue = handle_entry(handle, lvalue)
José Fonseca031b7382011-05-10 20:36:40 +010097 print ' if (retrace::verbosity >= 2) {'
José Fonsecaa10af892011-04-11 09:10:55 +010098 print ' std::cout << "%s " << size_t(%s) << " <- " << size_t(%s) << "\\n";' % (handle.name, lvalue, new_lvalue)
José Fonseca031b7382011-05-10 20:36:40 +010099 print ' }'
José Fonsecaa10af892011-04-11 09:10:55 +0100100 print ' %s = %s;' % (lvalue, new_lvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000101
102 def visit_blob(self, blob, lvalue, rvalue):
José Fonseca7ebb9e22011-05-06 09:58:45 +0100103 print ' %s = static_cast<%s>((%s).toPointer());' % (lvalue, blob, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000104
105 def visit_string(self, string, lvalue, rvalue):
José Fonseca7ebb9e22011-05-06 09:58:45 +0100106 print ' %s = (%s)((%s).toString());' % (lvalue, string.expr, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000107
108
José Fonsecaa10af892011-04-11 09:10:55 +0100109class OpaqueValueExtractor(ValueExtractor):
110 '''Value extractor that also understands opaque values.
111
112 Normally opaque values can't be retraced, unless they are being extracted
113 in the context of handles.'''
114
115 def visit_opaque(self, opaque, lvalue, rvalue):
José Fonseca7ebb9e22011-05-06 09:58:45 +0100116 print ' %s = static_cast<%s>((%s).toPointer());' % (lvalue, opaque, rvalue)
José Fonsecaa10af892011-04-11 09:10:55 +0100117
José Fonsecae0e61402010-11-25 15:03:23 +0000118
119class ValueWrapper(stdapi.Visitor):
120
121 def visit_literal(self, literal, lvalue, rvalue):
122 pass
123
124 def visit_alias(self, alias, lvalue, rvalue):
125 self.visit(alias.type, lvalue, rvalue)
126
127 def visit_enum(self, enum, lvalue, rvalue):
128 pass
129
130 def visit_bitmask(self, bitmask, lvalue, rvalue):
131 pass
132
133 def visit_array(self, array, lvalue, rvalue):
134 print ' const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (array.id, rvalue)
135 print ' if (__a%s) {' % (array.id)
136 length = '__a%s->values.size()' % array.id
137 index = '__j' + array.id
José Fonsecadbaae492011-04-21 09:28:10 +0100138 print ' for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
José Fonsecae0e61402010-11-25 15:03:23 +0000139 try:
140 self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.id, index))
141 finally:
142 print ' }'
143 print ' }'
144
145 def visit_pointer(self, pointer, lvalue, rvalue):
146 print ' const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (pointer.id, rvalue)
147 print ' if (__a%s) {' % (pointer.id)
148 try:
149 self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.id,))
150 finally:
151 print ' }'
152
José Fonsecae0e61402010-11-25 15:03:23 +0000153 def visit_handle(self, handle, lvalue, rvalue):
José Fonsecaa10af892011-04-11 09:10:55 +0100154 print ' %s __orig_result;' % handle.type
155 OpaqueValueExtractor().visit(handle.type, '__orig_result', rvalue);
José Fonsecad922e1d2010-11-25 17:14:02 +0000156 if handle.range is None:
José Fonsecaa10af892011-04-11 09:10:55 +0100157 rvalue = "__orig_result"
José Fonseca8a844ae2010-12-06 18:50:52 +0000158 entry = handle_entry(handle, rvalue)
159 print " %s = %s;" % (entry, lvalue)
José Fonseca031b7382011-05-10 20:36:40 +0100160 print ' if (retrace::verbosity >= 2) {'
José Fonseca8a844ae2010-12-06 18:50:52 +0000161 print ' std::cout << "{handle.name} " << {rvalue} << " -> " << {lvalue} << "\\n";'.format(**locals())
José Fonseca031b7382011-05-10 20:36:40 +0100162 print ' }'
José Fonsecad922e1d2010-11-25 17:14:02 +0000163 else:
164 i = '__h' + handle.id
José Fonseca8a844ae2010-12-06 18:50:52 +0000165 lvalue = "%s + %s" % (lvalue, i)
José Fonsecaa10af892011-04-11 09:10:55 +0100166 rvalue = "__orig_result + %s" % (i,)
José Fonseca8a844ae2010-12-06 18:50:52 +0000167 entry = handle_entry(handle, rvalue)
José Fonsecadbaae492011-04-21 09:28:10 +0100168 print ' for ({handle.type} {i} = 0; {i} < {handle.range}; ++{i}) {{'.format(**locals())
José Fonseca8a844ae2010-12-06 18:50:52 +0000169 print ' {entry} = {lvalue};'.format(**locals())
José Fonseca031b7382011-05-10 20:36:40 +0100170 print ' if (retrace::verbosity >= 2) {'
José Fonseca8a844ae2010-12-06 18:50:52 +0000171 print ' std::cout << "{handle.name} " << ({rvalue}) << " -> " << ({lvalue}) << "\\n";'.format(**locals())
José Fonseca031b7382011-05-10 20:36:40 +0100172 print ' }'
José Fonsecad922e1d2010-11-25 17:14:02 +0000173 print ' }'
José Fonsecae0e61402010-11-25 15:03:23 +0000174
175 def visit_blob(self, blob, lvalue, rvalue):
176 pass
177
178 def visit_string(self, string, lvalue, rvalue):
179 pass
180
181
José Fonsecae0e61402010-11-25 15:03:23 +0000182class Retracer:
183
184 def retrace_function(self, function):
185 print 'static void retrace_%s(Trace::Call &call) {' % function.name
José Fonseca62212972011-03-23 13:22:55 +0000186 self.retrace_function_body(function)
187 print '}'
188 print
189
190 def retrace_function_body(self, function):
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100191 if not function.sideeffects:
José Fonseca9109c3a2011-05-24 19:31:26 +0100192 print ' (void)call;'
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100193 return
194
José Fonsecae0e61402010-11-25 15:03:23 +0000195 success = True
196 for arg in function.args:
197 arg_type = ConstRemover().visit(arg.type)
198 #print ' // %s -> %s' % (arg.type, arg_type)
199 print ' %s %s;' % (arg_type, arg.name)
200 rvalue = 'call.arg(%u)' % (arg.index,)
201 lvalue = arg.name
202 try:
José Fonsecadacd8dd2010-11-25 17:50:26 +0000203 self.extract_arg(function, arg, arg_type, lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000204 except NotImplementedError:
205 success = False
206 print ' %s = 0; // FIXME' % arg.name
207 if not success:
José Fonseca9109c3a2011-05-24 19:31:26 +0100208 print ' if (1) {'
José Fonsecafa15d332010-11-25 20:22:39 +0000209 self.fail_function(function)
José Fonseca9109c3a2011-05-24 19:31:26 +0100210 print ' }'
José Fonsecafa15d332010-11-25 20:22:39 +0000211 self.call_function(function)
José Fonsecae0e61402010-11-25 15:03:23 +0000212 for arg in function.args:
213 if arg.output:
214 arg_type = ConstRemover().visit(arg.type)
215 rvalue = 'call.arg(%u)' % (arg.index,)
216 lvalue = arg.name
217 try:
218 ValueWrapper().visit(arg_type, lvalue, rvalue)
219 except NotImplementedError:
220 print ' // FIXME: %s' % arg.name
221 if function.type is not stdapi.Void:
222 rvalue = '*call.ret'
223 lvalue = '__result'
224 try:
225 ValueWrapper().visit(function.type, lvalue, rvalue)
226 except NotImplementedError:
227 print ' // FIXME: result'
José Fonsecae0e61402010-11-25 15:03:23 +0000228
José Fonsecafa15d332010-11-25 20:22:39 +0000229 def fail_function(self, function):
José Fonseca32871ed2011-04-10 13:40:52 +0100230 print ' if (retrace::verbosity >= 0)'
José Fonseca5e687162011-02-09 15:11:12 +0000231 print ' std::cerr << "warning: unsupported call %s\\n";' % function.name
José Fonsecafa15d332010-11-25 20:22:39 +0000232 print ' return;'
233
José Fonsecadacd8dd2010-11-25 17:50:26 +0000234 def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
235 ValueExtractor().visit(arg_type, lvalue, rvalue)
José Fonsecafd34e4e2011-06-03 19:34:29 +0100236
237 def extract_opaque_arg(self, function, arg, arg_type, lvalue, rvalue):
238 OpaqueValueExtractor().visit(arg_type, lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000239
José Fonsecafa15d332010-11-25 20:22:39 +0000240 def call_function(self, function):
241 arg_names = ", ".join([arg.name for arg in function.args])
242 if function.type is not stdapi.Void:
243 print ' %s __result;' % (function.type)
244 print ' __result = %s(%s);' % (function.name, arg_names)
José Fonseca974a3fb2011-05-23 21:15:12 +0100245 print ' (void)__result;'
José Fonsecafa15d332010-11-25 20:22:39 +0000246 else:
247 print ' %s(%s);' % (function.name, arg_names)
248
José Fonseca4441baf2010-11-25 19:55:27 +0000249 def filter_function(self, function):
250 return True
251
José Fonseca2741ed82011-10-07 23:36:39 +0100252 table_name = 'retrace::callbacks'
253
José Fonsecae0e61402010-11-25 15:03:23 +0000254 def retrace_functions(self, functions):
José Fonseca4441baf2010-11-25 19:55:27 +0000255 functions = filter(self.filter_function, functions)
256
José Fonsecae0e61402010-11-25 15:03:23 +0000257 for function in functions:
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100258 self.retrace_function(function)
José Fonsecae0e61402010-11-25 15:03:23 +0000259
José Fonseca2741ed82011-10-07 23:36:39 +0100260 print 'const retrace::Entry %s[] = {' % self.table_name
261 for function in functions:
262 print ' {"%s", &retrace_%s},' % (function.name, function.name)
263 print ' {NULL, NULL}'
264 print '};'
José Fonsecae0e61402010-11-25 15:03:23 +0000265 print
266
267
268 def retrace_api(self, api):
269
270 print '#include "trace_parser.hpp"'
José Fonseca91343f52011-04-01 08:37:06 +0100271 print '#include "retrace.hpp"'
José Fonsecae0e61402010-11-25 15:03:23 +0000272 print
273
274 types = api.all_types()
275 handles = [type for type in types if isinstance(type, stdapi.Handle)]
José Fonsecad922e1d2010-11-25 17:14:02 +0000276 handle_names = set()
José Fonsecae0e61402010-11-25 15:03:23 +0000277 for handle in handles:
José Fonsecad922e1d2010-11-25 17:14:02 +0000278 if handle.name not in handle_names:
José Fonseca8a844ae2010-12-06 18:50:52 +0000279 if handle.key is None:
José Fonseca91343f52011-04-01 08:37:06 +0100280 print 'static retrace::map<%s> __%s_map;' % (handle.type, handle.name)
José Fonseca8a844ae2010-12-06 18:50:52 +0000281 else:
282 key_name, key_type = handle.key
José Fonseca91343f52011-04-01 08:37:06 +0100283 print 'static std::map<%s, retrace::map<%s> > __%s_map;' % (key_type, handle.type, handle.name)
José Fonsecad922e1d2010-11-25 17:14:02 +0000284 handle_names.add(handle.name)
José Fonsecae0e61402010-11-25 15:03:23 +0000285 print
286
José Fonsecae0e61402010-11-25 15:03:23 +0000287 self.retrace_functions(api.functions)
288