]> git.cworth.org Git - apitrace/blob - trace.py
Merge branch 'd3dretrace'
[apitrace] / trace.py
1 ##########################################################################
2 #
3 # Copyright 2008-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 """Common trace code generation."""
27
28
29 import specs.stdapi as stdapi
30
31
32 def getWrapperInterfaceName(interface):
33     return "Wrap" + interface.expr
34
35
36 class ComplexValueSerializer(stdapi.OnceVisitor):
37     '''Type visitors which generates serialization functions for
38     complex types.
39     
40     Simple types are serialized inline.
41     '''
42
43     def __init__(self, serializer):
44         stdapi.OnceVisitor.__init__(self)
45         self.serializer = serializer
46
47     def visitVoid(self, literal):
48         pass
49
50     def visitLiteral(self, literal):
51         pass
52
53     def visitString(self, string):
54         pass
55
56     def visitConst(self, const):
57         self.visit(const.type)
58
59     def visitStruct(self, struct):
60         for type, name in struct.members:
61             self.visit(type)
62         print 'static void _write__%s(const %s &value) {' % (struct.tag, struct.expr)
63         print '    static const char * members[%u] = {' % (len(struct.members),)
64         for type, name,  in struct.members:
65             print '        "%s",' % (name,)
66         print '    };'
67         print '    static const trace::StructSig sig = {'
68         print '       %u, "%s", %u, members' % (struct.id, struct.name, len(struct.members))
69         print '    };'
70         print '    trace::localWriter.beginStruct(&sig);'
71         for type, name in struct.members:
72             self.serializer.visit(type, 'value.%s' % (name,))
73         print '    trace::localWriter.endStruct();'
74         print '}'
75         print
76
77     def visitArray(self, array):
78         self.visit(array.type)
79
80     def visitBlob(self, array):
81         pass
82
83     def visitEnum(self, enum):
84         print 'static const trace::EnumValue __enum%s_values[] = {' % (enum.tag)
85         for value in enum.values:
86             print '   {"%s", %s},' % (value, value)
87         print '};'
88         print
89         print 'static const trace::EnumSig __enum%s_sig = {' % (enum.tag)
90         print '   %u, %u, __enum%s_values' % (enum.id, len(enum.values), enum.tag)
91         print '};'
92         print
93
94     def visitBitmask(self, bitmask):
95         print 'static const trace::BitmaskFlag __bitmask%s_flags[] = {' % (bitmask.tag)
96         for value in bitmask.values:
97             print '   {"%s", %s},' % (value, value)
98         print '};'
99         print
100         print 'static const trace::BitmaskSig __bitmask%s_sig = {' % (bitmask.tag)
101         print '   %u, %u, __bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
102         print '};'
103         print
104
105     def visitPointer(self, pointer):
106         self.visit(pointer.type)
107
108     def visitIntPointer(self, pointer):
109         pass
110
111     def visitObjPointer(self, pointer):
112         self.visit(pointer.type)
113
114     def visitLinearPointer(self, pointer):
115         self.visit(pointer.type)
116
117     def visitHandle(self, handle):
118         self.visit(handle.type)
119
120     def visitReference(self, reference):
121         self.visit(reference.type)
122
123     def visitAlias(self, alias):
124         self.visit(alias.type)
125
126     def visitOpaque(self, opaque):
127         pass
128
129     def visitInterface(self, interface):
130         pass
131
132     def visitPolymorphic(self, polymorphic):
133         print 'static void _write__%s(int selector, const %s & value) {' % (polymorphic.tag, polymorphic.expr)
134         print '    switch (selector) {'
135         for cases, type in polymorphic.iterSwitch():
136             for case in cases:
137                 print '    %s:' % case
138             self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
139             print '        break;'
140         print '    }'
141         print '}'
142         print
143
144
145 class ValueSerializer(stdapi.Visitor):
146     '''Visitor which generates code to serialize any type.
147     
148     Simple types are serialized inline here, whereas the serialization of
149     complex types is dispatched to the serialization functions generated by
150     ComplexValueSerializer visitor above.
151     '''
152
153     def visitLiteral(self, literal, instance):
154         print '    trace::localWriter.write%s(%s);' % (literal.kind, instance)
155
156     def visitString(self, string, instance):
157         if string.kind == 'String':
158             cast = 'const char *'
159         elif string.kind == 'WString':
160             cast = 'const wchar_t *'
161         else:
162             assert False
163         if cast != string.expr:
164             # reinterpret_cast is necessary for GLubyte * <=> char *
165             instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
166         if string.length is not None:
167             length = ', %s' % string.length
168         else:
169             length = ''
170         print '    trace::localWriter.write%s(%s%s);' % (string.kind, instance, length)
171
172     def visitConst(self, const, instance):
173         self.visit(const.type, instance)
174
175     def visitStruct(self, struct, instance):
176         print '    _write__%s(%s);' % (struct.tag, instance)
177
178     def visitArray(self, array, instance):
179         length = '__c' + array.type.tag
180         index = '__i' + array.type.tag
181         print '    if (%s) {' % instance
182         print '        size_t %s = %s;' % (length, array.length)
183         print '        trace::localWriter.beginArray(%s);' % length
184         print '        for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
185         print '            trace::localWriter.beginElement();'
186         self.visit(array.type, '(%s)[%s]' % (instance, index))
187         print '            trace::localWriter.endElement();'
188         print '        }'
189         print '        trace::localWriter.endArray();'
190         print '    } else {'
191         print '        trace::localWriter.writeNull();'
192         print '    }'
193
194     def visitBlob(self, blob, instance):
195         print '    trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size)
196
197     def visitEnum(self, enum, instance):
198         print '    trace::localWriter.writeEnum(&__enum%s_sig, %s);' % (enum.tag, instance)
199
200     def visitBitmask(self, bitmask, instance):
201         print '    trace::localWriter.writeBitmask(&__bitmask%s_sig, %s);' % (bitmask.tag, instance)
202
203     def visitPointer(self, pointer, instance):
204         print '    if (%s) {' % instance
205         print '        trace::localWriter.beginArray(1);'
206         print '        trace::localWriter.beginElement();'
207         self.visit(pointer.type, "*" + instance)
208         print '        trace::localWriter.endElement();'
209         print '        trace::localWriter.endArray();'
210         print '    } else {'
211         print '        trace::localWriter.writeNull();'
212         print '    }'
213
214     def visitIntPointer(self, pointer, instance):
215         print '    trace::localWriter.writeOpaque((const void *)%s);' % instance
216
217     def visitObjPointer(self, pointer, instance):
218         print '    trace::localWriter.writeOpaque((const void *)%s);' % instance
219
220     def visitLinearPointer(self, pointer, instance):
221         print '    trace::localWriter.writeOpaque((const void *)%s);' % instance
222
223     def visitReference(self, reference, instance):
224         self.visit(reference.type, instance)
225
226     def visitHandle(self, handle, instance):
227         self.visit(handle.type, instance)
228
229     def visitAlias(self, alias, instance):
230         self.visit(alias.type, instance)
231
232     def visitOpaque(self, opaque, instance):
233         print '    trace::localWriter.writeOpaque((const void *)%s);' % instance
234
235     def visitInterface(self, interface, instance):
236         print '    trace::localWriter.writeOpaque((const void *)&%s);' % instance
237
238     def visitPolymorphic(self, polymorphic, instance):
239         print '    _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
240
241
242 class ValueWrapper(stdapi.Visitor):
243     '''Type visitor which will generate the code to wrap an instance.
244     
245     Wrapping is necessary mostly for interfaces, however interface pointers can
246     appear anywhere inside complex types.
247     '''
248
249     def visitVoid(self, type, instance):
250         raise NotImplementedError
251
252     def visitLiteral(self, type, instance):
253         pass
254
255     def visitString(self, type, instance):
256         pass
257
258     def visitConst(self, type, instance):
259         pass
260
261     def visitStruct(self, struct, instance):
262         for type, name in struct.members:
263             self.visit(type, "(%s).%s" % (instance, name))
264
265     def visitArray(self, array, instance):
266         # XXX: actually it is possible to return an array of pointers
267         pass
268
269     def visitBlob(self, blob, instance):
270         pass
271
272     def visitEnum(self, enum, instance):
273         pass
274
275     def visitBitmask(self, bitmask, instance):
276         pass
277
278     def visitPointer(self, pointer, instance):
279         print "    if (%s) {" % instance
280         self.visit(pointer.type, "*" + instance)
281         print "    }"
282     
283     def visitIntPointer(self, pointer, instance):
284         pass
285
286     def visitObjPointer(self, pointer, instance):
287         print "    if (%s) {" % instance
288         self.visit(pointer.type, "*" + instance)
289         print "    }"
290     
291     def visitLinearPointer(self, pointer, instance):
292         pass
293
294     def visitReference(self, reference, instance):
295         self.visit(reference.type, instance)
296     
297     def visitHandle(self, handle, instance):
298         self.visit(handle.type, instance)
299
300     def visitAlias(self, alias, instance):
301         self.visit(alias.type, instance)
302
303     def visitOpaque(self, opaque, instance):
304         pass
305     
306     def visitInterface(self, interface, instance):
307         assert instance.startswith('*')
308         instance = instance[1:]
309         print "    if (%s) {" % instance
310         print "        %s = new %s(%s);" % (instance, getWrapperInterfaceName(interface), instance)
311         print "    }"
312     
313     def visitPolymorphic(self, type, instance):
314         # XXX: There might be polymorphic values that need wrapping in the future
315         pass
316
317
318 class ValueUnwrapper(ValueWrapper):
319     '''Reverse of ValueWrapper.'''
320
321     def visitInterface(self, interface, instance):
322         assert instance.startswith('*')
323         instance = instance[1:]
324         print r'    if (%s) {' % instance
325         print r'        %s *pWrapper = static_cast<%s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
326         print r'        if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
327         print r'            %s = pWrapper->m_pInstance;' % (instance,)
328         print r'        } else {'
329         print r'            os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
330         print r'        }'
331         print r'    }'
332
333
334 class Tracer:
335     '''Base class to orchestrate the code generation of API tracing.'''
336
337     def __init__(self):
338         self.api = None
339
340     def serializerFactory(self):
341         '''Create a serializer.
342         
343         Can be overriden by derived classes to inject their own serialzer.
344         '''
345
346         return ValueSerializer()
347
348     def trace_api(self, api):
349         self.api = api
350
351         self.header(api)
352
353         # Includes
354         for header in api.headers:
355             print header
356         print
357
358         # Generate the serializer functions
359         types = api.getAllTypes()
360         visitor = ComplexValueSerializer(self.serializerFactory())
361         map(visitor.visit, types)
362         print
363
364         # Interfaces wrapers
365         interfaces = api.getAllInterfaces()
366         map(self.declareWrapperInterface, interfaces)
367         map(self.implementWrapperInterface, interfaces)
368         print
369
370         # Function wrappers
371         map(self.traceFunctionDecl, api.functions)
372         map(self.traceFunctionImpl, api.functions)
373         print
374
375         self.footer(api)
376
377     def header(self, api):
378         pass
379
380     def footer(self, api):
381         pass
382
383     def traceFunctionDecl(self, function):
384         # Per-function declarations
385
386         if function.args:
387             print 'static const char * __%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
388         else:
389             print 'static const char ** __%s_args = NULL;' % (function.name,)
390         print 'static const trace::FunctionSig __%s_sig = {%u, "%s", %u, __%s_args};' % (function.name, function.id, function.name, len(function.args), function.name)
391         print
392
393     def isFunctionPublic(self, function):
394         return True
395
396     def traceFunctionImpl(self, function):
397         if self.isFunctionPublic(function):
398             print 'extern "C" PUBLIC'
399         else:
400             print 'extern "C" PRIVATE'
401         print function.prototype() + ' {'
402         if function.type is not stdapi.Void:
403             print '    %s __result;' % function.type
404         self.traceFunctionImplBody(function)
405         if function.type is not stdapi.Void:
406             self.wrapRet(function, "__result")
407             print '    return __result;'
408         print '}'
409         print
410
411     def traceFunctionImplBody(self, function):
412         print '    unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
413         for arg in function.args:
414             if not arg.output:
415                 self.unwrapArg(function, arg)
416                 self.serializeArg(function, arg)
417         print '    trace::localWriter.endEnter();'
418         self.invokeFunction(function)
419         print '    trace::localWriter.beginLeave(__call);'
420         for arg in function.args:
421             if arg.output:
422                 self.serializeArg(function, arg)
423                 self.wrapArg(function, arg)
424         if function.type is not stdapi.Void:
425             self.serializeRet(function, "__result")
426         print '    trace::localWriter.endLeave();'
427
428     def invokeFunction(self, function, prefix='__', suffix=''):
429         if function.type is stdapi.Void:
430             result = ''
431         else:
432             result = '__result = '
433         dispatch = prefix + function.name + suffix
434         print '    %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
435
436     def serializeArg(self, function, arg):
437         print '    trace::localWriter.beginArg(%u);' % (arg.index,)
438         self.serializeArgValue(function, arg)
439         print '    trace::localWriter.endArg();'
440
441     def serializeArgValue(self, function, arg):
442         self.serializeValue(arg.type, arg.name)
443
444     def wrapArg(self, function, arg):
445         self.wrapValue(arg.type, arg.name)
446
447     def unwrapArg(self, function, arg):
448         self.unwrapValue(arg.type, arg.name)
449
450     def serializeRet(self, function, instance):
451         print '    trace::localWriter.beginReturn();'
452         self.serializeValue(function.type, instance)
453         print '    trace::localWriter.endReturn();'
454
455     def serializeValue(self, type, instance):
456         serializer = self.serializerFactory()
457         serializer.visit(type, instance)
458
459     def wrapRet(self, function, instance):
460         self.wrapValue(function.type, instance)
461
462     def unwrapRet(self, function, instance):
463         self.unwrapValue(function.type, instance)
464
465     def wrapValue(self, type, instance):
466         visitor = ValueWrapper()
467         visitor.visit(type, instance)
468
469     def unwrapValue(self, type, instance):
470         visitor = ValueUnwrapper()
471         visitor.visit(type, instance)
472
473     def declareWrapperInterface(self, interface):
474         print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
475         print "{"
476         print "public:"
477         print "    %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
478         print "    virtual ~%s();" % getWrapperInterfaceName(interface)
479         print
480         for method in interface.iterMethods():
481             print "    " + method.prototype() + ";"
482         print
483         self.declareWrapperInterfaceVariables(interface)
484         print "};"
485         print
486
487     def declareWrapperInterfaceVariables(self, interface):
488         #print "private:"
489         print "    DWORD m_dwMagic;"
490         print "    %s * m_pInstance;" % (interface.name,)
491
492     def implementWrapperInterface(self, interface):
493         print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
494         print '    m_dwMagic = 0xd8365d6c;'
495         print '    m_pInstance = pInstance;'
496         print '}'
497         print
498         print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
499         print '}'
500         print
501         for base, method in interface.iterBaseMethods():
502             self.implementWrapperInterfaceMethod(interface, base, method)
503         print
504
505     def implementWrapperInterfaceMethod(self, interface, base, method):
506         print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
507         if method.type is not stdapi.Void:
508             print '    %s __result;' % method.type
509     
510         self.implementWrapperInterfaceMethodBody(interface, base, method)
511     
512         if method.type is not stdapi.Void:
513             print '    return __result;'
514         print '}'
515         print
516
517     def implementWrapperInterfaceMethodBody(self, interface, base, method):
518         print '    static const char * __args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
519         print '    static const trace::FunctionSig __sig = {%u, "%s", %u, __args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1)
520         print '    unsigned __call = trace::localWriter.beginEnter(&__sig);'
521         print '    trace::localWriter.beginArg(0);'
522         print '    trace::localWriter.writeOpaque((const void *)m_pInstance);'
523         print '    trace::localWriter.endArg();'
524
525         from specs.winapi import REFIID
526         from specs.stdapi import Pointer, Opaque, Interface
527
528         riid = None
529         for arg in method.args:
530             if not arg.output:
531                 self.unwrapArg(method, arg)
532                 self.serializeArg(method, arg)
533                 if arg.type is REFIID:
534                     riid = arg
535         print '    trace::localWriter.endEnter();'
536         
537         self.invokeMethod(interface, base, method)
538
539         print '    trace::localWriter.beginLeave(__call);'
540         for arg in method.args:
541             if arg.output:
542                 self.serializeArg(method, arg)
543                 self.wrapArg(method, arg)
544                 if riid is not None and isinstance(arg.type, Pointer):
545                     if isinstance(arg.type.type, Opaque):
546                         self.wrapIid(interface, method, riid, arg)
547                     else:
548                         assert isinstance(arg.type.type, Pointer)
549                         assert isinstance(arg.type.type.type, Interface)
550
551         if method.type is not stdapi.Void:
552             print '    trace::localWriter.beginReturn();'
553             self.serializeValue(method.type, "__result")
554             print '    trace::localWriter.endReturn();'
555             self.wrapValue(method.type, '__result')
556         print '    trace::localWriter.endLeave();'
557         if method.name == 'Release':
558             assert method.type is not stdapi.Void
559             print '    if (!__result)'
560             print '        delete this;'
561
562     def wrapIid(self, interface, method, riid, out):
563             print '    if (%s && *%s) {' % (out.name, out.name)
564             print '        if (*%s == m_pInstance) {' % (out.name,)
565             print '            *%s = this;' % (out.name,)
566             print '        }'
567             for iface in self.api.getAllInterfaces():
568                 print r'        else if (%s == IID_%s) {' % (riid.name, iface.name)
569                 print r'            *%s = new Wrap%s((%s *) *%s);' % (out.name, iface.name, iface.name, out.name)
570                 print r'        }'
571             print r'        else {'
572             print r'            os::log("apitrace: warning: %s::%s: unknown IID {0x%08lX,0x%04X,0x%04X,{0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X}}\n",'
573             print r'                    "%s", "%s",' % (interface.name, method.name)
574             print r'                    %s.Data1, %s.Data2, %s.Data3,' % (riid.name, riid.name, riid.name)
575             print r'                    %s.Data4[0],' % (riid.name,)
576             print r'                    %s.Data4[1],' % (riid.name,)
577             print r'                    %s.Data4[2],' % (riid.name,)
578             print r'                    %s.Data4[3],' % (riid.name,)
579             print r'                    %s.Data4[4],' % (riid.name,)
580             print r'                    %s.Data4[5],' % (riid.name,)
581             print r'                    %s.Data4[6],' % (riid.name,)
582             print r'                    %s.Data4[7]);' % (riid.name,)
583             print r'        }'
584             print '    }'
585
586     def invokeMethod(self, interface, base, method):
587         if method.type is stdapi.Void:
588             result = ''
589         else:
590             result = '__result = '
591         print '    %sstatic_cast<%s *>(m_pInstance)->%s(%s);' % (result, base, method.name, ', '.join([str(arg.name) for arg in method.args]))
592     
593     def emit_memcpy(self, dest, src, length):
594         print '        unsigned __call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
595         print '        trace::localWriter.beginArg(0);'
596         print '        trace::localWriter.writeOpaque(%s);' % dest
597         print '        trace::localWriter.endArg();'
598         print '        trace::localWriter.beginArg(1);'
599         print '        trace::localWriter.writeBlob(%s, %s);' % (src, length)
600         print '        trace::localWriter.endArg();'
601         print '        trace::localWriter.beginArg(2);'
602         print '        trace::localWriter.writeUInt(%s);' % length
603         print '        trace::localWriter.endArg();'
604         print '        trace::localWriter.endEnter();'
605         print '        trace::localWriter.beginLeave(__call);'
606         print '        trace::localWriter.endLeave();'
607