]> git.cworth.org Git - apitrace/blob - wrappers/trace.py
stash: Trace and replay of gnome-shell works
[apitrace] / wrappers / 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 # Adjust path
30 import os.path
31 import sys
32 sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
33
34
35 import specs.stdapi as stdapi
36
37
38 def getWrapperInterfaceName(interface):
39     return "Wrap" + interface.expr
40
41
42
43 class ComplexValueSerializer(stdapi.OnceVisitor):
44     '''Type visitors which generates serialization functions for
45     complex types.
46     
47     Simple types are serialized inline.
48     '''
49
50     def __init__(self, serializer):
51         stdapi.OnceVisitor.__init__(self)
52         self.serializer = serializer
53
54     def visitVoid(self, literal):
55         pass
56
57     def visitLiteral(self, literal):
58         pass
59
60     def visitString(self, string):
61         pass
62
63     def visitConst(self, const):
64         self.visit(const.type)
65
66     def visitStruct(self, struct):
67         print 'static const char * _struct%s_members[%u] = {' % (struct.tag, len(struct.members))
68         for type, name,  in struct.members:
69             if name is None:
70                 print '    "",'
71             else:
72                 print '    "%s",' % (name,)
73         print '};'
74         print 'static const trace::StructSig _struct%s_sig = {' % (struct.tag,)
75         if struct.name is None:
76             structName = '""'
77         else:
78             structName = '"%s"' % struct.name
79         print '    %u, %s, %u, _struct%s_members' % (struct.id, structName, len(struct.members), struct.tag)
80         print '};'
81         print
82
83     def visitArray(self, array):
84         self.visit(array.type)
85
86     def visitBlob(self, array):
87         pass
88
89     def visitEnum(self, enum):
90         print 'static const trace::EnumValue _enum%s_values[] = {' % (enum.tag)
91         for value in enum.values:
92             print '    {"%s", %s},' % (value, value)
93         print '};'
94         print
95         print 'static const trace::EnumSig _enum%s_sig = {' % (enum.tag)
96         print '    %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag)
97         print '};'
98         print
99
100     def visitBitmask(self, bitmask):
101         print 'static const trace::BitmaskFlag _bitmask%s_flags[] = {' % (bitmask.tag)
102         for value in bitmask.values:
103             print '    {"%s", %s},' % (value, value)
104         print '};'
105         print
106         print 'static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag)
107         print '    %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
108         print '};'
109         print
110
111     def visitPointer(self, pointer):
112         self.visit(pointer.type)
113
114     def visitIntPointer(self, pointer):
115         pass
116
117     def visitObjPointer(self, pointer):
118         self.visit(pointer.type)
119
120     def visitLinearPointer(self, pointer):
121         self.visit(pointer.type)
122
123     def visitHandle(self, handle):
124         self.visit(handle.type)
125
126     def visitReference(self, reference):
127         self.visit(reference.type)
128
129     def visitAlias(self, alias):
130         self.visit(alias.type)
131
132     def visitOpaque(self, opaque):
133         pass
134
135     def visitInterface(self, interface):
136         pass
137
138     def visitPolymorphic(self, polymorphic):
139         if not polymorphic.contextLess:
140             return
141         print 'static void _write__%s(int selector, %s const & value) {' % (polymorphic.tag, polymorphic.expr)
142         print '    switch (selector) {'
143         for cases, type in polymorphic.iterSwitch():
144             for case in cases:
145                 print '    %s:' % case
146             self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
147             print '        break;'
148         print '    }'
149         print '}'
150         print
151
152
153 class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
154     '''Visitor which generates code to serialize any type.
155     
156     Simple types are serialized inline here, whereas the serialization of
157     complex types is dispatched to the serialization functions generated by
158     ComplexValueSerializer visitor above.
159     '''
160
161     def visitLiteral(self, literal, instance):
162         print '    trace::localWriter.write%s(%s);' % (literal.kind, instance)
163
164     def visitString(self, string, instance):
165         if not string.wide:
166             cast = 'const char *'
167             suffix = 'String'
168         else:
169             cast = 'const wchar_t *'
170             suffix = 'WString'
171         if cast != string.expr:
172             # reinterpret_cast is necessary for GLubyte * <=> char *
173             instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
174         if string.length is not None:
175             length = ', %s' % self.expand(string.length)
176         else:
177             length = ''
178         print '    trace::localWriter.write%s(%s%s);' % (suffix, instance, length)
179
180     def visitConst(self, const, instance):
181         self.visit(const.type, instance)
182
183     def visitStruct(self, struct, instance):
184         print '    trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,)
185         for member in struct.members:
186             self.visitMember(member, instance)
187         print '    trace::localWriter.endStruct();'
188
189     def visitArray(self, array, instance):
190         length = '_c' + array.type.tag
191         index = '_i' + array.type.tag
192         array_length = self.expand(array.length)
193         print '    if (%s) {' % instance
194         print '        size_t %s = %s > 0 ? %s : 0;' % (length, array_length, array_length)
195         print '        trace::localWriter.beginArray(%s);' % length
196         print '        for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
197         print '            trace::localWriter.beginElement();'
198         self.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
199         print '            trace::localWriter.endElement();'
200         print '        }'
201         print '        trace::localWriter.endArray();'
202         print '    } else {'
203         print '        trace::localWriter.writeNull();'
204         print '    }'
205
206     def visitBlob(self, blob, instance):
207         print '    trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
208
209     def visitEnum(self, enum, instance):
210         print '    trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
211
212     def visitBitmask(self, bitmask, instance):
213         print '    trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
214
215     def visitPointer(self, pointer, instance):
216         print '    if (%s) {' % instance
217         print '        trace::localWriter.beginArray(1);'
218         print '        trace::localWriter.beginElement();'
219         self.visit(pointer.type, "*" + instance)
220         print '        trace::localWriter.endElement();'
221         print '        trace::localWriter.endArray();'
222         print '    } else {'
223         print '        trace::localWriter.writeNull();'
224         print '    }'
225
226     def visitIntPointer(self, pointer, instance):
227         print '    trace::localWriter.writePointer((uintptr_t)%s);' % instance
228
229     def visitObjPointer(self, pointer, instance):
230         print '    trace::localWriter.writePointer((uintptr_t)%s);' % instance
231
232     def visitLinearPointer(self, pointer, instance):
233         print '    trace::localWriter.writePointer((uintptr_t)%s);' % instance
234
235     def visitReference(self, reference, instance):
236         self.visit(reference.type, instance)
237
238     def visitHandle(self, handle, instance):
239         self.visit(handle.type, instance)
240
241     def visitAlias(self, alias, instance):
242         self.visit(alias.type, instance)
243
244     def visitOpaque(self, opaque, instance):
245         print '    trace::localWriter.writePointer((uintptr_t)%s);' % instance
246
247     def visitInterface(self, interface, instance):
248         assert False
249
250     def visitPolymorphic(self, polymorphic, instance):
251         if polymorphic.contextLess:
252             print '    _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
253         else:
254             switchExpr = self.expand(polymorphic.switchExpr)
255             print '    switch (%s) {' % switchExpr
256             for cases, type in polymorphic.iterSwitch():
257                 for case in cases:
258                     print '    %s:' % case
259                 caseInstance = instance
260                 if type.expr is not None:
261                     caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
262                 self.visit(type, caseInstance)
263                 print '        break;'
264             if polymorphic.defaultType is None:
265                 print r'    default:'
266                 print r'        os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,)
267                 print r'        trace::localWriter.writeNull();'
268                 print r'        break;'
269             print '    }'
270
271
272 class WrapDecider(stdapi.Traverser):
273     '''Type visitor which will decide wheter this type will need wrapping or not.
274     
275     For complex types (arrays, structures), we need to know this before hand.
276     '''
277
278     def __init__(self):
279         self.needsWrapping = False
280
281     def visitLinearPointer(self, void):
282         pass
283
284     def visitInterface(self, interface):
285         self.needsWrapping = True
286
287
288 class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
289     '''Type visitor which will generate the code to wrap an instance.
290     
291     Wrapping is necessary mostly for interfaces, however interface pointers can
292     appear anywhere inside complex types.
293     '''
294
295     def visitStruct(self, struct, instance):
296         for member in struct.members:
297             self.visitMember(member, instance)
298
299     def visitArray(self, array, instance):
300         array_length = self.expand(array.length)
301         print "    if (%s) {" % instance
302         print "        for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
303         self.visitElement('_i', array.type, instance + "[_i]")
304         print "        }"
305         print "    }"
306
307     def visitPointer(self, pointer, instance):
308         print "    if (%s) {" % instance
309         self.visit(pointer.type, "*" + instance)
310         print "    }"
311     
312     def visitObjPointer(self, pointer, instance):
313         elem_type = pointer.type.mutable()
314         if isinstance(elem_type, stdapi.Interface):
315             self.visitInterfacePointer(elem_type, instance)
316         elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
317             self.visitInterfacePointer(elem_type.type, instance)
318         else:
319             self.visitPointer(pointer, instance)
320     
321     def visitInterface(self, interface, instance):
322         raise NotImplementedError
323
324     def visitInterfacePointer(self, interface, instance):
325         print "    if (%s) {" % instance
326         print "        %s = %s::_Create(__FUNCTION__, %s);" % (instance, getWrapperInterfaceName(interface), instance)
327         print "    }"
328     
329     def visitPolymorphic(self, type, instance):
330         # XXX: There might be polymorphic values that need wrapping in the future
331         raise NotImplementedError
332
333
334 class ValueUnwrapper(ValueWrapper):
335     '''Reverse of ValueWrapper.'''
336
337     allocated = False
338
339     def visitStruct(self, struct, instance):
340         if not self.allocated:
341             # Argument is constant. We need to create a non const
342             print '    {'
343             print "        %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct)
344             print '        *_t = %s;' % (instance,)
345             assert instance.startswith('*')
346             print '        %s = _t;' % (instance[1:],)
347             instance = '*_t'
348             self.allocated = True
349             try:
350                 return ValueWrapper.visitStruct(self, struct, instance)
351             finally:
352                 print '    }'
353         else:
354             return ValueWrapper.visitStruct(self, struct, instance)
355
356     def visitArray(self, array, instance):
357         if self.allocated or isinstance(instance, stdapi.Interface):
358             return ValueWrapper.visitArray(self, array, instance)
359         array_length = self.expand(array.length)
360         elem_type = array.type.mutable()
361         print "    if (%s && %s) {" % (instance, array_length)
362         print "        %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array_length)
363         print "        for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
364         print "            _t[_i] = %s[_i];" % instance 
365         self.allocated = True
366         self.visit(array.type, "_t[_i]")
367         print "        }"
368         print "        %s = _t;" % instance
369         print "    }"
370
371     def visitInterfacePointer(self, interface, instance):
372         print r'    if (%s) {' % instance
373         print r'        const %s *pWrapper = static_cast<const %s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
374         print r'        if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
375         print r'            %s = pWrapper->m_pInstance;' % (instance,)
376         print r'        } else {'
377         print r'            os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
378         print r'        }'
379         print r'    }'
380
381
382 class Tracer:
383     '''Base class to orchestrate the code generation of API tracing.'''
384
385     # 0-3 are reserved to memcpy, malloc, free, and realloc
386     __id = 4
387
388     def __init__(self):
389         self.api = None
390
391     def serializerFactory(self):
392         '''Create a serializer.
393         
394         Can be overriden by derived classes to inject their own serialzer.
395         '''
396
397         return ValueSerializer()
398
399     def traceApi(self, api):
400         self.api = api
401
402         self.header(api)
403
404         # Includes
405         for module in api.modules:
406             for header in module.headers:
407                 print header
408         print
409
410         # Generate the serializer functions
411         types = api.getAllTypes()
412         visitor = ComplexValueSerializer(self.serializerFactory())
413         map(visitor.visit, types)
414         print
415
416         # Interfaces wrapers
417         self.traceInterfaces(api)
418
419         # Function wrappers
420         self.interface = None
421         self.base = None
422         for function in api.getAllFunctions():
423             self.traceFunctionDecl(function)
424         for function in api.getAllFunctions():
425             self.traceFunctionImpl(function)
426         print
427
428         self.footer(api)
429
430     def header(self, api):
431         print '#ifdef _WIN32'
432         print '#  include <malloc.h> // alloca'
433         print '#  ifndef alloca'
434         print '#    define alloca _alloca'
435         print '#  endif'
436         print '#else'
437         print '#  include <alloca.h> // alloca'
438         print '#endif'
439         print
440         print '#include "trace.hpp"'
441         print
442         print 'static std::map<void *, void *> g_WrappedObjects;'
443
444     def footer(self, api):
445         pass
446
447     def traceFunctionDecl(self, function):
448         # Per-function declarations
449
450         if not function.internal:
451             if function.args:
452                 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
453             else:
454                 print 'static const char ** _%s_args = NULL;' % (function.name,)
455             print 'static const trace::FunctionSig _%s_sig = {%u, "%s", %u, _%s_args};' % (function.name, self.getFunctionSigId(), function.name, len(function.args), function.name)
456             print
457
458     def getFunctionSigId(self):
459         id = Tracer.__id
460         Tracer.__id += 1
461         return id
462
463     def isFunctionPublic(self, function):
464         return True
465
466     def traceFunctionImpl(self, function):
467         if self.isFunctionPublic(function):
468             print 'extern "C" PUBLIC'
469         else:
470             print 'extern "C" PRIVATE'
471         print function.prototype() + ' {'
472         if function.type is not stdapi.Void:
473             print '    %s _result;' % function.type
474
475         # No-op if tracing is disabled
476         print '    if (!trace::isTracingEnabled()) {'
477         Tracer.invokeFunction(self, function)
478         if function.type is not stdapi.Void:
479             print '        return _result;'
480         else:
481             print '        return;'
482         print '    }'
483
484         self.traceFunctionImplBody(function)
485         if function.type is not stdapi.Void:
486             print '    return _result;'
487         print '}'
488         print
489
490     def traceFunctionImplBody(self, function):
491         if function.name == 'glXCreatePixmap':
492             print '    emit_fake_x_create_pixmap(dpy, pixmap);'
493         if function.name == 'glXBindTexImageEXT':
494             print '    emit_fake_put_image_data(display, underlying_x_pixmaps[drawable]);'
495         if not function.internal:
496             print '    unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
497             for arg in function.args:
498                 if not arg.output:
499                     self.unwrapArg(function, arg)
500             for arg in function.args:
501                 if not arg.output:
502                     self.serializeArg(function, arg)
503             print '    trace::localWriter.endEnter();'
504         self.invokeFunction(function)
505         if function.name == 'glXCreatePixmap':
506             print '    underlying_x_pixmaps[_result] = pixmap;'
507         if not function.internal:
508             print '    trace::localWriter.beginLeave(_call);'
509             print '    if (%s) {' % self.wasFunctionSuccessful(function)
510             for arg in function.args:
511                 if arg.output:
512                     self.serializeArg(function, arg)
513                     self.wrapArg(function, arg)
514             print '    }'
515             if function.type is not stdapi.Void:
516                 self.serializeRet(function, "_result")
517             if function.type is not stdapi.Void:
518                 self.wrapRet(function, "_result")
519             print '    trace::localWriter.endLeave();'
520
521     def invokeFunction(self, function, prefix='_', suffix=''):
522         if function.type is stdapi.Void:
523             result = ''
524         else:
525             result = '_result = '
526         dispatch = prefix + function.name + suffix
527         print '    %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
528
529     def wasFunctionSuccessful(self, function):
530         if function.type is stdapi.Void:
531             return 'true'
532         if str(function.type) == 'HRESULT':
533             return 'SUCCEEDED(_result)'
534         return 'true'
535
536     def serializeArg(self, function, arg):
537         print '    trace::localWriter.beginArg(%u);' % (arg.index,)
538         self.serializeArgValue(function, arg)
539         print '    trace::localWriter.endArg();'
540
541     def serializeArgValue(self, function, arg):
542         self.serializeValue(arg.type, arg.name)
543
544     def wrapArg(self, function, arg):
545         assert not isinstance(arg.type, stdapi.ObjPointer)
546
547         from specs.winapi import REFIID
548         riid = None
549         for other_arg in function.args:
550             if not other_arg.output and other_arg.type is REFIID:
551                 riid = other_arg
552         if riid is not None \
553            and isinstance(arg.type, stdapi.Pointer) \
554            and isinstance(arg.type.type, stdapi.ObjPointer):
555             self.wrapIid(function, riid, arg)
556             return
557
558         self.wrapValue(arg.type, arg.name)
559
560     def unwrapArg(self, function, arg):
561         self.unwrapValue(arg.type, arg.name)
562
563     def serializeRet(self, function, instance):
564         print '    trace::localWriter.beginReturn();'
565         self.serializeValue(function.type, instance)
566         print '    trace::localWriter.endReturn();'
567
568     def serializeValue(self, type, instance):
569         serializer = self.serializerFactory()
570         serializer.visit(type, instance)
571
572     def wrapRet(self, function, instance):
573         self.wrapValue(function.type, instance)
574
575     def needsWrapping(self, type):
576         visitor = WrapDecider()
577         visitor.visit(type)
578         return visitor.needsWrapping
579
580     def wrapValue(self, type, instance):
581         if self.needsWrapping(type):
582             visitor = ValueWrapper()
583             visitor.visit(type, instance)
584
585     def unwrapValue(self, type, instance):
586         if self.needsWrapping(type):
587             visitor = ValueUnwrapper()
588             visitor.visit(type, instance)
589
590     def traceInterfaces(self, api):
591         interfaces = api.getAllInterfaces()
592         if not interfaces:
593             return
594         map(self.declareWrapperInterface, interfaces)
595         self.implementIidWrapper(api)
596         map(self.implementWrapperInterface, interfaces)
597         print
598
599     def declareWrapperInterface(self, interface):
600         print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
601         print "{"
602         print "private:"
603         print "    %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
604         print "    virtual ~%s();" % getWrapperInterfaceName(interface)
605         print "public:"
606         print "    static %s* _Create(const char *functionName, %s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
607         print
608         for method in interface.iterMethods():
609             print "    " + method.prototype() + ";"
610         print
611         #print "private:"
612         for type, name, value in self.enumWrapperInterfaceVariables(interface):
613             print '    %s %s;' % (type, name)
614         for i in range(64):
615             print r'    virtual void _dummy%i(void) const {' % i
616             print r'        os::log("error: %s: unexpected virtual method\n");' % interface.name
617             print r'        os::abort();'
618             print r'    }'
619         print "};"
620         print
621
622     def enumWrapperInterfaceVariables(self, interface):
623         return [
624             ("DWORD", "m_dwMagic", "0xd8365d6c"),
625             ("%s *" % interface.name, "m_pInstance", "pInstance"),
626             ("void *", "m_pVtbl", "*(void **)pInstance"),
627             ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
628         ] 
629
630     def implementWrapperInterface(self, interface):
631         self.interface = interface
632
633         # Private constructor
634         print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
635         for type, name, value in self.enumWrapperInterfaceVariables(interface):
636             print '    %s = %s;' % (name, value)
637         print '}'
638         print
639
640         # Public constructor
641         print '%s *%s::_Create(const char *functionName, %s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
642         print r'    std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pInstance);'
643         print r'    if (it != g_WrappedObjects.end()) {'
644         print r'        Wrap%s *pWrapper = (Wrap%s *)it->second;' % (interface.name, interface.name)
645         print r'        assert(pWrapper);'
646         print r'        assert(pWrapper->m_dwMagic == 0xd8365d6c);'
647         print r'        assert(pWrapper->m_pInstance == pInstance);'
648         print r'        if (pWrapper->m_pVtbl == *(void **)pInstance &&'
649         print r'            pWrapper->m_NumMethods >= %s) {' % len(list(interface.iterBaseMethods()))
650         #print r'            os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);'
651         print r'            return pWrapper;'
652         print r'        }'
653         print r'    }'
654         print r'    Wrap%s *pWrapper = new Wrap%s(pInstance);' % (interface.name, interface.name)
655         #print r'    os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);' % interface.name
656         print r'    g_WrappedObjects[pInstance] = pWrapper;'
657         print r'    return pWrapper;'
658         print '}'
659         print
660
661         # Destructor
662         print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
663         #print r'        os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", m_pInstance, this, m_pVtbl);' % interface.name
664         print r'        g_WrappedObjects.erase(m_pInstance);'
665         print '}'
666         print
667         
668         for base, method in interface.iterBaseMethods():
669             self.base = base
670             self.implementWrapperInterfaceMethod(interface, base, method)
671
672         print
673
674     def implementWrapperInterfaceMethod(self, interface, base, method):
675         print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
676
677         if False:
678             print r'    os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (getWrapperInterfaceName(interface) + '::' + method.name)
679
680         if method.type is not stdapi.Void:
681             print '    %s _result;' % method.type
682     
683         self.implementWrapperInterfaceMethodBody(interface, base, method)
684     
685         if method.type is not stdapi.Void:
686             print '    return _result;'
687         print '}'
688         print
689
690     def implementWrapperInterfaceMethodBody(self, interface, base, method):
691         assert not method.internal
692
693         print '    static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
694         print '    static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (self.getFunctionSigId(), interface.name + '::' + method.name, len(method.args) + 1)
695
696         print '    %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
697
698         print '    unsigned _call = trace::localWriter.beginEnter(&_sig);'
699         print '    trace::localWriter.beginArg(0);'
700         print '    trace::localWriter.writePointer((uintptr_t)m_pInstance);'
701         print '    trace::localWriter.endArg();'
702         for arg in method.args:
703             if not arg.output:
704                 self.unwrapArg(method, arg)
705         for arg in method.args:
706             if not arg.output:
707                 self.serializeArg(method, arg)
708         print '    trace::localWriter.endEnter();'
709         
710         self.invokeMethod(interface, base, method)
711
712         print '    trace::localWriter.beginLeave(_call);'
713
714         print '    if (%s) {' % self.wasFunctionSuccessful(method)
715         for arg in method.args:
716             if arg.output:
717                 self.serializeArg(method, arg)
718                 self.wrapArg(method, arg)
719         print '    }'
720
721         if method.type is not stdapi.Void:
722             self.serializeRet(method, '_result')
723         if method.type is not stdapi.Void:
724             self.wrapRet(method, '_result')
725
726         if method.name == 'Release':
727             assert method.type is not stdapi.Void
728             print r'    if (!_result) {'
729             print r'        delete this;'
730             print r'    }'
731         
732         print '    trace::localWriter.endLeave();'
733
734     def implementIidWrapper(self, api):
735         print r'static void'
736         print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
737         print r'    os::log("apitrace: warning: %s: %s IID {0x%08lX,0x%04X,0x%04X,{0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X}}\n",'
738         print r'            functionName, reason,'
739         print r'            riid.Data1, riid.Data2, riid.Data3,'
740         print r'            riid.Data4[0], riid.Data4[1], riid.Data4[2], riid.Data4[3], riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7]);'
741         print r'}'
742         print 
743         print r'static void'
744         print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
745         print r'    if (!ppvObj || !*ppvObj) {'
746         print r'        return;'
747         print r'    }'
748         else_ = ''
749         for iface in api.getAllInterfaces():
750             print r'    %sif (riid == IID_%s) {' % (else_, iface.name)
751             print r'        *ppvObj = Wrap%s::_Create(functionName, (%s *) *ppvObj);' % (iface.name, iface.name)
752             print r'    }'
753             else_ = 'else '
754         print r'    %s{' % else_
755         print r'        warnIID(functionName, riid, "unknown");'
756         print r'    }'
757         print r'}'
758         print
759
760     def wrapIid(self, function, riid, out):
761         # Cast output arg to `void **` if necessary
762         out_name = out.name
763         obj_type = out.type.type.type
764         if not obj_type is stdapi.Void:
765             assert isinstance(obj_type, stdapi.Interface)
766             out_name = 'reinterpret_cast<void * *>(%s)' % out_name
767
768         print r'    if (%s && *%s) {' % (out.name, out.name)
769         functionName = function.name
770         else_ = ''
771         if self.interface is not None:
772             functionName = self.interface.name + '::' + functionName
773             print r'        if (*%s == m_pInstance &&' % (out_name,)
774             print r'            (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
775             print r'            *%s = this;' % (out_name,)
776             print r'        }'
777             else_ = 'else '
778         print r'        %s{' % else_
779         print r'             wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
780         print r'        }'
781         print r'    }'
782
783     def invokeMethod(self, interface, base, method):
784         if method.type is stdapi.Void:
785             result = ''
786         else:
787             result = '_result = '
788         print '    %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
789     
790     def emit_memcpy(self, dest, src, length):
791         print '        unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
792         print '        trace::localWriter.beginArg(0);'
793         print '        trace::localWriter.writePointer((uintptr_t)%s);' % dest
794         print '        trace::localWriter.endArg();'
795         print '        trace::localWriter.beginArg(1);'
796         print '        trace::localWriter.writeBlob(%s, %s);' % (src, length)
797         print '        trace::localWriter.endArg();'
798         print '        trace::localWriter.beginArg(2);'
799         print '        trace::localWriter.writeUInt(%s);' % length
800         print '        trace::localWriter.endArg();'
801         print '        trace::localWriter.endEnter();'
802         print '        trace::localWriter.beginLeave(_call);'
803         print '        trace::localWriter.endLeave();'
804     
805     def fake_call(self, function, args):
806         print '            unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
807         for arg, instance in zip(function.args, args):
808             assert not arg.output
809             print '            trace::localWriter.beginArg(%u);' % (arg.index,)
810             self.serializeValue(arg.type, instance)
811             print '            trace::localWriter.endArg();'
812         print '            trace::localWriter.endEnter();'
813         print '            trace::localWriter.beginLeave(_fake_call);'
814         print '            trace::localWriter.endLeave();'
815