blob: 9e42be38b874edd0f25404f7773e6cad2975a311 [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é Fonsecae0e61402010-11-25 15:03:23 +000029import stdapi
30import 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é Fonseca32871ed2011-04-10 13:40:52 +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)
100 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é Fonseca32871ed2011-04-10 13:40:52 +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é Fonsecad922e1d2010-11-25 17:14:02 +0000162 else:
163 i = '__h' + handle.id
José Fonseca8a844ae2010-12-06 18:50:52 +0000164 lvalue = "%s + %s" % (lvalue, i)
José Fonsecaa10af892011-04-11 09:10:55 +0100165 rvalue = "__orig_result + %s" % (i,)
José Fonseca8a844ae2010-12-06 18:50:52 +0000166 entry = handle_entry(handle, rvalue)
José Fonsecadbaae492011-04-21 09:28:10 +0100167 print ' for ({handle.type} {i} = 0; {i} < {handle.range}; ++{i}) {{'.format(**locals())
José Fonseca8a844ae2010-12-06 18:50:52 +0000168 print ' {entry} = {lvalue};'.format(**locals())
José Fonseca32871ed2011-04-10 13:40:52 +0100169 print ' if (retrace::verbosity >= 2)'
José Fonseca8a844ae2010-12-06 18:50:52 +0000170 print ' std::cout << "{handle.name} " << ({rvalue}) << " -> " << ({lvalue}) << "\\n";'.format(**locals())
José Fonsecad922e1d2010-11-25 17:14:02 +0000171 print ' }'
José Fonsecae0e61402010-11-25 15:03:23 +0000172
173 def visit_blob(self, blob, lvalue, rvalue):
174 pass
175
176 def visit_string(self, string, lvalue, rvalue):
177 pass
178
179
José Fonsecae0e61402010-11-25 15:03:23 +0000180class Retracer:
181
182 def retrace_function(self, function):
183 print 'static void retrace_%s(Trace::Call &call) {' % function.name
José Fonseca62212972011-03-23 13:22:55 +0000184 self.retrace_function_body(function)
185 print '}'
186 print
187
188 def retrace_function_body(self, function):
José Fonsecae0e61402010-11-25 15:03:23 +0000189 success = True
190 for arg in function.args:
191 arg_type = ConstRemover().visit(arg.type)
192 #print ' // %s -> %s' % (arg.type, arg_type)
193 print ' %s %s;' % (arg_type, arg.name)
194 rvalue = 'call.arg(%u)' % (arg.index,)
195 lvalue = arg.name
196 try:
José Fonsecadacd8dd2010-11-25 17:50:26 +0000197 self.extract_arg(function, arg, arg_type, lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000198 except NotImplementedError:
199 success = False
200 print ' %s = 0; // FIXME' % arg.name
201 if not success:
José Fonsecafa15d332010-11-25 20:22:39 +0000202 self.fail_function(function)
203 self.call_function(function)
José Fonsecae0e61402010-11-25 15:03:23 +0000204 for arg in function.args:
205 if arg.output:
206 arg_type = ConstRemover().visit(arg.type)
207 rvalue = 'call.arg(%u)' % (arg.index,)
208 lvalue = arg.name
209 try:
210 ValueWrapper().visit(arg_type, lvalue, rvalue)
211 except NotImplementedError:
212 print ' // FIXME: %s' % arg.name
213 if function.type is not stdapi.Void:
214 rvalue = '*call.ret'
215 lvalue = '__result'
216 try:
217 ValueWrapper().visit(function.type, lvalue, rvalue)
218 except NotImplementedError:
219 print ' // FIXME: result'
José Fonsecae0e61402010-11-25 15:03:23 +0000220
José Fonsecafa15d332010-11-25 20:22:39 +0000221 def fail_function(self, function):
José Fonseca32871ed2011-04-10 13:40:52 +0100222 print ' if (retrace::verbosity >= 0)'
José Fonseca5e687162011-02-09 15:11:12 +0000223 print ' std::cerr << "warning: unsupported call %s\\n";' % function.name
José Fonsecafa15d332010-11-25 20:22:39 +0000224 print ' return;'
225
José Fonsecadacd8dd2010-11-25 17:50:26 +0000226 def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
227 ValueExtractor().visit(arg_type, lvalue, rvalue)
José Fonsecae0e61402010-11-25 15:03:23 +0000228
José Fonsecafa15d332010-11-25 20:22:39 +0000229 def call_function(self, function):
230 arg_names = ", ".join([arg.name for arg in function.args])
231 if function.type is not stdapi.Void:
232 print ' %s __result;' % (function.type)
233 print ' __result = %s(%s);' % (function.name, arg_names)
234 else:
235 print ' %s(%s);' % (function.name, arg_names)
236
José Fonseca4441baf2010-11-25 19:55:27 +0000237 def filter_function(self, function):
238 return True
239
José Fonsecae0e61402010-11-25 15:03:23 +0000240 def retrace_functions(self, functions):
José Fonseca4441baf2010-11-25 19:55:27 +0000241 functions = filter(self.filter_function, functions)
242
José Fonsecae0e61402010-11-25 15:03:23 +0000243 for function in functions:
244 if function.sideeffects:
245 self.retrace_function(function)
246
José Fonsecaf237aad2011-05-05 00:54:04 +0100247 print 'void retrace::retrace_call(Trace::Call &call) {'
José Fonseca522b7442010-11-27 15:30:40 +0000248 print ' const char *name = call.name().c_str();'
José Fonsecae0e61402010-11-25 15:03:23 +0000249 print
José Fonseca522b7442010-11-27 15:30:40 +0000250
251 func_dict = dict([(function.name, function) for function in functions])
252
253 def handle_case(function_name):
254 function = func_dict[function_name]
José Fonsecae0e61402010-11-25 15:03:23 +0000255 if function.sideeffects:
José Fonsecae0e61402010-11-25 15:03:23 +0000256 print ' retrace_%s(call);' % function.name
José Fonsecaf237aad2011-05-05 00:54:04 +0100257 print ' return;'
José Fonseca522b7442010-11-27 15:30:40 +0000258
259 string_switch('name', func_dict.keys(), handle_case)
260
José Fonseca45b28c42011-05-05 01:08:00 +0100261 print ' retrace_unknown(call);'
José Fonsecae0e61402010-11-25 15:03:23 +0000262 print '}'
263 print
264
265
266 def retrace_api(self, api):
267
268 print '#include "trace_parser.hpp"'
José Fonseca91343f52011-04-01 08:37:06 +0100269 print '#include "retrace.hpp"'
José Fonsecae0e61402010-11-25 15:03:23 +0000270 print
271
272 types = api.all_types()
273 handles = [type for type in types if isinstance(type, stdapi.Handle)]
José Fonsecad922e1d2010-11-25 17:14:02 +0000274 handle_names = set()
José Fonsecae0e61402010-11-25 15:03:23 +0000275 for handle in handles:
José Fonsecad922e1d2010-11-25 17:14:02 +0000276 if handle.name not in handle_names:
José Fonseca8a844ae2010-12-06 18:50:52 +0000277 if handle.key is None:
José Fonseca91343f52011-04-01 08:37:06 +0100278 print 'static retrace::map<%s> __%s_map;' % (handle.type, handle.name)
José Fonseca8a844ae2010-12-06 18:50:52 +0000279 else:
280 key_name, key_type = handle.key
José Fonseca91343f52011-04-01 08:37:06 +0100281 print 'static std::map<%s, retrace::map<%s> > __%s_map;' % (key_type, handle.type, handle.name)
José Fonsecad922e1d2010-11-25 17:14:02 +0000282 handle_names.add(handle.name)
José Fonsecae0e61402010-11-25 15:03:23 +0000283 print
284
José Fonsecae0e61402010-11-25 15:03:23 +0000285 self.retrace_functions(api.functions)
286