]> git.cworth.org Git - apitrace/blob - retrace.py
Dump the full set of constants on D3D.
[apitrace] / retrace.py
1 ##########################################################################
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
27 """Generic retracing code generator."""
28
29 import stdapi
30 import glapi
31 from codegen import *
32
33
34 class ConstRemover(stdapi.Rebuilder):
35
36     def visit_const(self, const):
37         return const.type
38
39     def visit_opaque(self, opaque):
40         expr = opaque.expr
41         if expr.startswith('const '):
42             expr = expr[6:]
43         return stdapi.Opaque(expr)
44
45
46 def handle_entry(handle, value):
47     if handle.key is None:
48         return "__%s_map[%s]" % (handle.name, value)
49     else:
50         key_name, key_type = handle.key
51         return "__%s_map[%s][%s]" % (handle.name, key_name, value)
52
53
54 class ValueExtractor(stdapi.Visitor):
55
56     def visit_literal(self, literal, lvalue, rvalue):
57         if literal.format == 'Bool':
58             print '    %s = static_cast<bool>(%s);' % (lvalue, rvalue)
59         else:
60             print '    %s = %s;' % (lvalue, rvalue)
61
62     def visit_const(self, const, lvalue, rvalue):
63         self.visit(const.type, lvalue, rvalue)
64
65     def visit_alias(self, alias, lvalue, rvalue):
66         self.visit(alias.type, lvalue, rvalue)
67     
68     def visit_enum(self, enum, lvalue, rvalue):
69         print '    %s = %s;' % (lvalue, rvalue)
70
71     def visit_bitmask(self, bitmask, lvalue, rvalue):
72         self.visit(bitmask.type, lvalue, rvalue)
73
74     def visit_array(self, array, lvalue, rvalue):
75         print '    const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (array.id, rvalue)
76         print '    if (__a%s) {' % (array.id)
77         length = '__a%s->values.size()' % array.id
78         print '        %s = new %s[%s];' % (lvalue, array.type, length)
79         index = '__j' + array.id
80         print '        for(size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
81         try:
82             self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.id, index))
83         finally:
84             print '        }'
85             print '    } else {'
86             print '        %s = NULL;' % lvalue
87             print '    }'
88     
89     def visit_pointer(self, pointer, lvalue, rvalue):
90         print '    const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (pointer.id, rvalue)
91         print '    if (__a%s) {' % (pointer.id)
92         print '        %s = new %s;' % (lvalue, pointer.type)
93         try:
94             self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.id,))
95         finally:
96             print '    } else {'
97             print '        %s = NULL;' % lvalue
98             print '    }'
99
100     def visit_handle(self, handle, lvalue, rvalue):
101         OpaqueValueExtractor().visit(handle.type, lvalue, rvalue);
102         new_lvalue = handle_entry(handle, lvalue)
103         print '    if (retrace::verbosity >= 2)'
104         print '        std::cout << "%s " << size_t(%s) << " <- " << size_t(%s) << "\\n";' % (handle.name, lvalue, new_lvalue)
105         print '    %s = %s;' % (lvalue, new_lvalue)
106     
107     def visit_blob(self, blob, lvalue, rvalue):
108         print '    %s = static_cast<%s>((%s).blob());' % (lvalue, blob, rvalue)
109     
110     def visit_string(self, string, lvalue, rvalue):
111         print '    %s = (%s)((%s).string());' % (lvalue, string.expr, rvalue)
112
113
114 class OpaqueValueExtractor(ValueExtractor):
115     '''Value extractor that also understands opaque values.
116
117     Normally opaque values can't be retraced, unless they are being extracted
118     in the context of handles.'''
119
120     def visit_opaque(self, opaque, lvalue, rvalue):
121         print '    %s = static_cast<%s>((%s).blob());' % (lvalue, opaque, rvalue)
122
123
124 class ValueWrapper(stdapi.Visitor):
125
126     def visit_literal(self, literal, lvalue, rvalue):
127         pass
128
129     def visit_alias(self, alias, lvalue, rvalue):
130         self.visit(alias.type, lvalue, rvalue)
131     
132     def visit_enum(self, enum, lvalue, rvalue):
133         pass
134
135     def visit_bitmask(self, bitmask, lvalue, rvalue):
136         pass
137
138     def visit_array(self, array, lvalue, rvalue):
139         print '    const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (array.id, rvalue)
140         print '    if (__a%s) {' % (array.id)
141         length = '__a%s->values.size()' % array.id
142         index = '__j' + array.id
143         print '        for(size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
144         try:
145             self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.id, index))
146         finally:
147             print '        }'
148             print '    }'
149     
150     def visit_pointer(self, pointer, lvalue, rvalue):
151         print '    const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (pointer.id, rvalue)
152         print '    if (__a%s) {' % (pointer.id)
153         try:
154             self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.id,))
155         finally:
156             print '    }'
157     
158     def visit_handle(self, handle, lvalue, rvalue):
159         print '    %s __orig_result;' % handle.type
160         OpaqueValueExtractor().visit(handle.type, '__orig_result', rvalue);
161         if handle.range is None:
162             rvalue = "__orig_result"
163             entry = handle_entry(handle, rvalue) 
164             print "    %s = %s;" % (entry, lvalue)
165             print '    if (retrace::verbosity >= 2)'
166             print '        std::cout << "{handle.name} " << {rvalue} << " -> " << {lvalue} << "\\n";'.format(**locals())
167         else:
168             i = '__h' + handle.id
169             lvalue = "%s + %s" % (lvalue, i)
170             rvalue = "__orig_result + %s" % (i,)
171             entry = handle_entry(handle, rvalue) 
172             print '    for({handle.type} {i} = 0; {i} < {handle.range}; ++{i}) {{'.format(**locals())
173             print '        {entry} = {lvalue};'.format(**locals())
174             print '        if (retrace::verbosity >= 2)'
175             print '            std::cout << "{handle.name} " << ({rvalue}) << " -> " << ({lvalue}) << "\\n";'.format(**locals())
176             print '    }'
177     
178     def visit_blob(self, blob, lvalue, rvalue):
179         pass
180     
181     def visit_string(self, string, lvalue, rvalue):
182         pass
183
184
185 class Retracer:
186
187     def retrace_function(self, function):
188         print 'static void retrace_%s(Trace::Call &call) {' % function.name
189         self.retrace_function_body(function)
190         print '}'
191         print
192
193     def retrace_function_body(self, function):
194         success = True
195         for arg in function.args:
196             arg_type = ConstRemover().visit(arg.type)
197             #print '    // %s ->  %s' % (arg.type, arg_type)
198             print '    %s %s;' % (arg_type, arg.name)
199             rvalue = 'call.arg(%u)' % (arg.index,)
200             lvalue = arg.name
201             try:
202                 self.extract_arg(function, arg, arg_type, lvalue, rvalue)
203             except NotImplementedError:
204                 success = False
205                 print '    %s = 0; // FIXME' % arg.name
206         if not success:
207             self.fail_function(function)
208         self.call_function(function)
209         for arg in function.args:
210             if arg.output:
211                 arg_type = ConstRemover().visit(arg.type)
212                 rvalue = 'call.arg(%u)' % (arg.index,)
213                 lvalue = arg.name
214                 try:
215                     ValueWrapper().visit(arg_type, lvalue, rvalue)
216                 except NotImplementedError:
217                     print '   // FIXME: %s' % arg.name
218         if function.type is not stdapi.Void:
219             rvalue = '*call.ret'
220             lvalue = '__result'
221             try:
222                 ValueWrapper().visit(function.type, lvalue, rvalue)
223             except NotImplementedError:
224                 print '   // FIXME: result'
225
226     def fail_function(self, function):
227         print '    if (retrace::verbosity >= 0)'
228         print '        std::cerr << "warning: unsupported call %s\\n";' % function.name
229         print '    return;'
230
231     def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
232         ValueExtractor().visit(arg_type, lvalue, rvalue)
233
234     def call_function(self, function):
235         arg_names = ", ".join([arg.name for arg in function.args])
236         if function.type is not stdapi.Void:
237             print '    %s __result;' % (function.type)
238             print '    __result = %s(%s);' % (function.name, arg_names)
239         else:
240             print '    %s(%s);' % (function.name, arg_names)
241
242     def filter_function(self, function):
243         return True
244
245     def retrace_functions(self, functions):
246         functions = filter(self.filter_function, functions)
247
248         for function in functions:
249             if function.sideeffects:
250                 self.retrace_function(function)
251
252         print 'bool retrace::retrace_call(Trace::Call &call) {'
253         print '    const char *name = call.name().c_str();'
254         print
255         print '    if (retrace::verbosity >= 1) {'
256         print '        std::cout << call;'
257         print '        std::cout.flush();'
258         print '    };'
259         print
260
261         func_dict = dict([(function.name, function) for function in functions])
262
263         def handle_case(function_name):
264             function = func_dict[function_name]
265             if function.sideeffects:
266                 print '        retrace_%s(call);' % function.name
267             print '        return true;'
268     
269         string_switch('name', func_dict.keys(), handle_case)
270
271         print '    if (retrace::verbosity >= 0)'
272         print '        std::cerr << "warning: unknown call " << call.name() << "\\n";'
273         print '    return false;'
274         print '}'
275         print
276
277
278     def retrace_api(self, api):
279
280         print '#include "trace_parser.hpp"'
281         print '#include "retrace.hpp"'
282         print
283
284         types = api.all_types()
285         handles = [type for type in types if isinstance(type, stdapi.Handle)]
286         handle_names = set()
287         for handle in handles:
288             if handle.name not in handle_names:
289                 if handle.key is None:
290                     print 'static retrace::map<%s> __%s_map;' % (handle.type, handle.name)
291                 else:
292                     key_name, key_type = handle.key
293                     print 'static std::map<%s, retrace::map<%s> > __%s_map;' % (key_type, handle.type, handle.name)
294                 handle_names.add(handle.name)
295         print
296
297         self.retrace_functions(api.functions)
298