blob: 724f5220bee23dd65b8d8008ac886e92dda43fb4 [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é Fonseca522b7442010-11-27 15:30:40 +000031from codegen import *
José Fonsecae0e61402010-11-25 15:03:23 +000032
33
34class ConstRemover(stdapi.Rebuilder):
35
36 def visit_const(self, const):
37 return const.type
38
39 def visit_opaque(self, opaque):
José Fonsecaf01b7f52011-04-20 21:09:28 +010040 return opaque
José Fonsecae0e61402010-11-25 15:03:23 +000041
42
José Fonseca8a844ae2010-12-06 18:50:52 +000043def handle_entry(handle, value):
44 if handle.key is None:
45 return "__%s_map[%s]" % (handle.name, value)
46 else:
47 key_name, key_type = handle.key
48 return "__%s_map[%s][%s]" % (handle.name, key_name, value)
49
50
José Fonsecae0e61402010-11-25 15:03:23 +000051class ValueExtractor(stdapi.Visitor):
52
53 def visit_literal(self, literal, lvalue, rvalue):
José Fonseca56e093c2011-05-07 01:09:19 +010054 #if literal.format in ('Bool', 'UInt'):
55 print ' %s = (%s).to%s();' % (lvalue, rvalue, literal.format)
José Fonsecae0e61402010-11-25 15:03:23 +000056
57 def visit_const(self, const, lvalue, rvalue):
58 self.visit(const.type, lvalue, rvalue)
59
60 def visit_alias(self, alias, lvalue, rvalue):
61 self.visit(alias.type, lvalue, rvalue)
62
63 def visit_enum(self, enum, lvalue, rvalue):
José Fonseca56e093c2011-05-07 01:09:19 +010064 print ' %s = (%s).toSInt();' % (lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +000065
66 def visit_bitmask(self, bitmask, lvalue, rvalue):
67 self.visit(bitmask.type, lvalue, rvalue)
68
69 def visit_array(self, array, lvalue, rvalue):
70 print ' const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (array.id, rvalue)
71 print ' if (__a%s) {' % (array.id)
72 length = '__a%s->values.size()' % array.id
73 print ' %s = new %s[%s];' % (lvalue, array.type, length)
74 index = '__j' + array.id
José Fonsecadbaae492011-04-21 09:28:10 +010075 print ' for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
José Fonsecae0e61402010-11-25 15:03:23 +000076 try:
77 self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.id, index))
78 finally:
79 print ' }'
80 print ' } else {'
81 print ' %s = NULL;' % lvalue
82 print ' }'
83
84 def visit_pointer(self, pointer, lvalue, rvalue):
85 print ' const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (pointer.id, rvalue)
86 print ' if (__a%s) {' % (pointer.id)
87 print ' %s = new %s;' % (lvalue, pointer.type)
88 try:
89 self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.id,))
90 finally:
91 print ' } else {'
92 print ' %s = NULL;' % lvalue
93 print ' }'
94
95 def visit_handle(self, handle, lvalue, rvalue):
José Fonsecaa10af892011-04-11 09:10:55 +010096 OpaqueValueExtractor().visit(handle.type, lvalue, rvalue);
97 new_lvalue = handle_entry(handle, lvalue)
José Fonseca031b7382011-05-10 20:36:40 +010098 print ' if (retrace::verbosity >= 2) {'
José Fonsecaa10af892011-04-11 09:10:55 +010099 print ' std::cout << "%s " << size_t(%s) << " <- " << size_t(%s) << "\\n";' % (handle.name, lvalue, new_lvalue)
José Fonseca031b7382011-05-10 20:36:40 +0100100 print ' }'
José Fonsecaa10af892011-04-11 09:10:55 +0100101 print ' %s = %s;' % (lvalue, new_lvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000102
103 def visit_blob(self, blob, lvalue, rvalue):
José Fonseca7ebb9e22011-05-06 09:58:45 +0100104 print ' %s = static_cast<%s>((%s).toPointer());' % (lvalue, blob, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000105
106 def visit_string(self, string, lvalue, rvalue):
José Fonseca7ebb9e22011-05-06 09:58:45 +0100107 print ' %s = (%s)((%s).toString());' % (lvalue, string.expr, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000108
109
José Fonsecaa10af892011-04-11 09:10:55 +0100110class OpaqueValueExtractor(ValueExtractor):
111 '''Value extractor that also understands opaque values.
112
113 Normally opaque values can't be retraced, unless they are being extracted
114 in the context of handles.'''
115
116 def visit_opaque(self, opaque, lvalue, rvalue):
José Fonseca7ebb9e22011-05-06 09:58:45 +0100117 print ' %s = static_cast<%s>((%s).toPointer());' % (lvalue, opaque, rvalue)
José Fonsecaa10af892011-04-11 09:10:55 +0100118
José Fonsecae0e61402010-11-25 15:03:23 +0000119
120class ValueWrapper(stdapi.Visitor):
121
122 def visit_literal(self, literal, lvalue, rvalue):
123 pass
124
125 def visit_alias(self, alias, lvalue, rvalue):
126 self.visit(alias.type, lvalue, rvalue)
127
128 def visit_enum(self, enum, lvalue, rvalue):
129 pass
130
131 def visit_bitmask(self, bitmask, lvalue, rvalue):
132 pass
133
134 def visit_array(self, array, lvalue, rvalue):
135 print ' const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (array.id, rvalue)
136 print ' if (__a%s) {' % (array.id)
137 length = '__a%s->values.size()' % array.id
138 index = '__j' + array.id
José Fonsecadbaae492011-04-21 09:28:10 +0100139 print ' for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
José Fonsecae0e61402010-11-25 15:03:23 +0000140 try:
141 self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.id, index))
142 finally:
143 print ' }'
144 print ' }'
145
146 def visit_pointer(self, pointer, lvalue, rvalue):
147 print ' const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (pointer.id, rvalue)
148 print ' if (__a%s) {' % (pointer.id)
149 try:
150 self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.id,))
151 finally:
152 print ' }'
153
José Fonsecae0e61402010-11-25 15:03:23 +0000154 def visit_handle(self, handle, lvalue, rvalue):
José Fonsecaa10af892011-04-11 09:10:55 +0100155 print ' %s __orig_result;' % handle.type
156 OpaqueValueExtractor().visit(handle.type, '__orig_result', rvalue);
José Fonsecad922e1d2010-11-25 17:14:02 +0000157 if handle.range is None:
José Fonsecaa10af892011-04-11 09:10:55 +0100158 rvalue = "__orig_result"
José Fonseca8a844ae2010-12-06 18:50:52 +0000159 entry = handle_entry(handle, rvalue)
160 print " %s = %s;" % (entry, lvalue)
José Fonseca031b7382011-05-10 20:36:40 +0100161 print ' if (retrace::verbosity >= 2) {'
José Fonseca8a844ae2010-12-06 18:50:52 +0000162 print ' std::cout << "{handle.name} " << {rvalue} << " -> " << {lvalue} << "\\n";'.format(**locals())
José Fonseca031b7382011-05-10 20:36:40 +0100163 print ' }'
José Fonsecad922e1d2010-11-25 17:14:02 +0000164 else:
165 i = '__h' + handle.id
José Fonseca8a844ae2010-12-06 18:50:52 +0000166 lvalue = "%s + %s" % (lvalue, i)
José Fonsecaa10af892011-04-11 09:10:55 +0100167 rvalue = "__orig_result + %s" % (i,)
José Fonseca8a844ae2010-12-06 18:50:52 +0000168 entry = handle_entry(handle, rvalue)
José Fonsecadbaae492011-04-21 09:28:10 +0100169 print ' for ({handle.type} {i} = 0; {i} < {handle.range}; ++{i}) {{'.format(**locals())
José Fonseca8a844ae2010-12-06 18:50:52 +0000170 print ' {entry} = {lvalue};'.format(**locals())
José Fonseca031b7382011-05-10 20:36:40 +0100171 print ' if (retrace::verbosity >= 2) {'
José Fonseca8a844ae2010-12-06 18:50:52 +0000172 print ' std::cout << "{handle.name} " << ({rvalue}) << " -> " << ({lvalue}) << "\\n";'.format(**locals())
José Fonseca031b7382011-05-10 20:36:40 +0100173 print ' }'
José Fonsecad922e1d2010-11-25 17:14:02 +0000174 print ' }'
José Fonsecae0e61402010-11-25 15:03:23 +0000175
176 def visit_blob(self, blob, lvalue, rvalue):
177 pass
178
179 def visit_string(self, string, lvalue, rvalue):
180 pass
181
182
José Fonsecae0e61402010-11-25 15:03:23 +0000183class Retracer:
184
185 def retrace_function(self, function):
186 print 'static void retrace_%s(Trace::Call &call) {' % function.name
José Fonseca62212972011-03-23 13:22:55 +0000187 self.retrace_function_body(function)
188 print '}'
189 print
190
191 def retrace_function_body(self, function):
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100192 if not function.sideeffects:
José Fonseca9109c3a2011-05-24 19:31:26 +0100193 print ' (void)call;'
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100194 return
195
José Fonsecae0e61402010-11-25 15:03:23 +0000196 success = True
197 for arg in function.args:
198 arg_type = ConstRemover().visit(arg.type)
199 #print ' // %s -> %s' % (arg.type, arg_type)
200 print ' %s %s;' % (arg_type, arg.name)
201 rvalue = 'call.arg(%u)' % (arg.index,)
202 lvalue = arg.name
203 try:
José Fonsecadacd8dd2010-11-25 17:50:26 +0000204 self.extract_arg(function, arg, arg_type, lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000205 except NotImplementedError:
206 success = False
207 print ' %s = 0; // FIXME' % arg.name
208 if not success:
José Fonseca9109c3a2011-05-24 19:31:26 +0100209 print ' if (1) {'
José Fonsecafa15d332010-11-25 20:22:39 +0000210 self.fail_function(function)
José Fonseca9109c3a2011-05-24 19:31:26 +0100211 print ' }'
José Fonsecafa15d332010-11-25 20:22:39 +0000212 self.call_function(function)
José Fonsecae0e61402010-11-25 15:03:23 +0000213 for arg in function.args:
214 if arg.output:
215 arg_type = ConstRemover().visit(arg.type)
216 rvalue = 'call.arg(%u)' % (arg.index,)
217 lvalue = arg.name
218 try:
219 ValueWrapper().visit(arg_type, lvalue, rvalue)
220 except NotImplementedError:
221 print ' // FIXME: %s' % arg.name
222 if function.type is not stdapi.Void:
223 rvalue = '*call.ret'
224 lvalue = '__result'
225 try:
226 ValueWrapper().visit(function.type, lvalue, rvalue)
227 except NotImplementedError:
228 print ' // FIXME: result'
José Fonsecae0e61402010-11-25 15:03:23 +0000229
José Fonsecafa15d332010-11-25 20:22:39 +0000230 def fail_function(self, function):
José Fonseca32871ed2011-04-10 13:40:52 +0100231 print ' if (retrace::verbosity >= 0)'
José Fonseca5e687162011-02-09 15:11:12 +0000232 print ' std::cerr << "warning: unsupported call %s\\n";' % function.name
José Fonsecafa15d332010-11-25 20:22:39 +0000233 print ' return;'
234
José Fonsecadacd8dd2010-11-25 17:50:26 +0000235 def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
236 ValueExtractor().visit(arg_type, lvalue, rvalue)
José Fonsecafd34e4e2011-06-03 19:34:29 +0100237
238 def extract_opaque_arg(self, function, arg, arg_type, lvalue, rvalue):
239 OpaqueValueExtractor().visit(arg_type, lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000240
José Fonsecafa15d332010-11-25 20:22:39 +0000241 def call_function(self, function):
242 arg_names = ", ".join([arg.name for arg in function.args])
243 if function.type is not stdapi.Void:
244 print ' %s __result;' % (function.type)
245 print ' __result = %s(%s);' % (function.name, arg_names)
José Fonseca974a3fb2011-05-23 21:15:12 +0100246 print ' (void)__result;'
José Fonsecafa15d332010-11-25 20:22:39 +0000247 else:
248 print ' %s(%s);' % (function.name, arg_names)
249
José Fonseca4441baf2010-11-25 19:55:27 +0000250 def filter_function(self, function):
251 return True
252
José Fonsecae0e61402010-11-25 15:03:23 +0000253 def retrace_functions(self, functions):
José Fonseca4441baf2010-11-25 19:55:27 +0000254 functions = filter(self.filter_function, functions)
255
José Fonsecae0e61402010-11-25 15:03:23 +0000256 for function in functions:
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100257 self.retrace_function(function)
José Fonsecae0e61402010-11-25 15:03:23 +0000258
José Fonsecaf237aad2011-05-05 00:54:04 +0100259 print 'void retrace::retrace_call(Trace::Call &call) {'
José Fonseca05688972011-05-28 11:47:48 +0100260 print ' const char *name = call.name();'
José Fonsecae0e61402010-11-25 15:03:23 +0000261 print
José Fonseca522b7442010-11-27 15:30:40 +0000262
263 func_dict = dict([(function.name, function) for function in functions])
264
265 def handle_case(function_name):
266 function = func_dict[function_name]
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100267 print ' retrace_%s(call);' % function.name
José Fonsecaf237aad2011-05-05 00:54:04 +0100268 print ' return;'
José Fonseca522b7442010-11-27 15:30:40 +0000269
270 string_switch('name', func_dict.keys(), handle_case)
271
José Fonseca45b28c42011-05-05 01:08:00 +0100272 print ' retrace_unknown(call);'
José Fonsecae0e61402010-11-25 15:03:23 +0000273 print '}'
274 print
275
276
277 def retrace_api(self, api):
278
279 print '#include "trace_parser.hpp"'
José Fonseca91343f52011-04-01 08:37:06 +0100280 print '#include "retrace.hpp"'
José Fonsecae0e61402010-11-25 15:03:23 +0000281 print
282
283 types = api.all_types()
284 handles = [type for type in types if isinstance(type, stdapi.Handle)]
José Fonsecad922e1d2010-11-25 17:14:02 +0000285 handle_names = set()
José Fonsecae0e61402010-11-25 15:03:23 +0000286 for handle in handles:
José Fonsecad922e1d2010-11-25 17:14:02 +0000287 if handle.name not in handle_names:
José Fonseca8a844ae2010-12-06 18:50:52 +0000288 if handle.key is None:
José Fonseca91343f52011-04-01 08:37:06 +0100289 print 'static retrace::map<%s> __%s_map;' % (handle.type, handle.name)
José Fonseca8a844ae2010-12-06 18:50:52 +0000290 else:
291 key_name, key_type = handle.key
José Fonseca91343f52011-04-01 08:37:06 +0100292 print 'static std::map<%s, retrace::map<%s> > __%s_map;' % (key_type, handle.type, handle.name)
José Fonsecad922e1d2010-11-25 17:14:02 +0000293 handle_names.add(handle.name)
José Fonsecae0e61402010-11-25 15:03:23 +0000294 print
295
José Fonsecae0e61402010-11-25 15:03:23 +0000296 self.retrace_functions(api.functions)
297