]> git.cworth.org Git - apitrace/blob - wrappers/trace.py
cmake: Fix MSVC build.
[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, const %s & 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     def __init__(self):
386         self.api = None
387
388     def serializerFactory(self):
389         '''Create a serializer.
390         
391         Can be overriden by derived classes to inject their own serialzer.
392         '''
393
394         return ValueSerializer()
395
396     def traceApi(self, api):
397         self.api = api
398
399         self.header(api)
400
401         # Includes
402         for module in api.modules:
403             for header in module.headers:
404                 print header
405         print
406
407         # Generate the serializer functions
408         types = api.getAllTypes()
409         visitor = ComplexValueSerializer(self.serializerFactory())
410         map(visitor.visit, types)
411         print
412
413         # Interfaces wrapers
414         self.traceInterfaces(api)
415
416         # Function wrappers
417         self.interface = None
418         self.base = None
419         for function in api.getAllFunctions():
420             self.traceFunctionDecl(function)
421         for function in api.getAllFunctions():
422             self.traceFunctionImpl(function)
423         print
424
425         self.footer(api)
426
427     def header(self, api):
428         print '#ifdef _WIN32'
429         print '#  include <malloc.h> // alloca'
430         print '#  ifndef alloca'
431         print '#    define alloca _alloca'
432         print '#  endif'
433         print '#else'
434         print '#  include <alloca.h> // alloca'
435         print '#endif'
436         print
437         print '#include "trace.hpp"'
438         print
439         print 'static std::map<void *, void *> g_WrappedObjects;'
440
441     def footer(self, api):
442         pass
443
444     def traceFunctionDecl(self, function):
445         # Per-function declarations
446
447         if not function.internal:
448             if function.args:
449                 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
450             else:
451                 print 'static const char ** _%s_args = NULL;' % (function.name,)
452             print 'static const trace::FunctionSig _%s_sig = {%u, "%s", %u, _%s_args};' % (function.name, function.id, function.name, len(function.args), function.name)
453             print
454
455     def isFunctionPublic(self, function):
456         return True
457
458     def traceFunctionImpl(self, function):
459         if self.isFunctionPublic(function):
460             print 'extern "C" PUBLIC'
461         else:
462             print 'extern "C" PRIVATE'
463         print function.prototype() + ' {'
464         if function.type is not stdapi.Void:
465             print '    %s _result;' % function.type
466
467         # No-op if tracing is disabled
468         print '    if (!trace::isTracingEnabled()) {'
469         Tracer.invokeFunction(self, function)
470         if function.type is not stdapi.Void:
471             print '        return _result;'
472         else:
473             print '        return;'
474         print '    }'
475
476         self.traceFunctionImplBody(function)
477         if function.type is not stdapi.Void:
478             print '    return _result;'
479         print '}'
480         print
481
482     def traceFunctionImplBody(self, function):
483         if not function.internal:
484             print '    unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
485             for arg in function.args:
486                 if not arg.output:
487                     self.unwrapArg(function, arg)
488                     self.serializeArg(function, arg)
489             print '    trace::localWriter.endEnter();'
490         self.invokeFunction(function)
491         if not function.internal:
492             print '    trace::localWriter.beginLeave(_call);'
493             print '    if (%s) {' % self.wasFunctionSuccessful(function)
494             for arg in function.args:
495                 if arg.output:
496                     self.serializeArg(function, arg)
497                     self.wrapArg(function, arg)
498             print '    }'
499             if function.type is not stdapi.Void:
500                 self.serializeRet(function, "_result")
501             if function.type is not stdapi.Void:
502                 self.wrapRet(function, "_result")
503             print '    trace::localWriter.endLeave();'
504
505     def invokeFunction(self, function, prefix='_', suffix=''):
506         if function.type is stdapi.Void:
507             result = ''
508         else:
509             result = '_result = '
510         dispatch = prefix + function.name + suffix
511         print '    %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
512
513     def wasFunctionSuccessful(self, function):
514         if function.type is stdapi.Void:
515             return 'true'
516         if str(function.type) == 'HRESULT':
517             return 'SUCCEEDED(_result)'
518         return 'true'
519
520     def serializeArg(self, function, arg):
521         print '    trace::localWriter.beginArg(%u);' % (arg.index,)
522         self.serializeArgValue(function, arg)
523         print '    trace::localWriter.endArg();'
524
525     def serializeArgValue(self, function, arg):
526         self.serializeValue(arg.type, arg.name)
527
528     def wrapArg(self, function, arg):
529         assert not isinstance(arg.type, stdapi.ObjPointer)
530
531         from specs.winapi import REFIID
532         riid = None
533         for other_arg in function.args:
534             if not other_arg.output and other_arg.type is REFIID:
535                 riid = other_arg
536         if riid is not None \
537            and isinstance(arg.type, stdapi.Pointer) \
538            and isinstance(arg.type.type, stdapi.ObjPointer):
539             self.wrapIid(function, riid, arg)
540             return
541
542         self.wrapValue(arg.type, arg.name)
543
544     def unwrapArg(self, function, arg):
545         self.unwrapValue(arg.type, arg.name)
546
547     def serializeRet(self, function, instance):
548         print '    trace::localWriter.beginReturn();'
549         self.serializeValue(function.type, instance)
550         print '    trace::localWriter.endReturn();'
551
552     def serializeValue(self, type, instance):
553         serializer = self.serializerFactory()
554         serializer.visit(type, instance)
555
556     def wrapRet(self, function, instance):
557         self.wrapValue(function.type, instance)
558
559     def unwrapRet(self, function, instance):
560         self.unwrapValue(function.type, instance)
561
562     def needsWrapping(self, type):
563         visitor = WrapDecider()
564         visitor.visit(type)
565         return visitor.needsWrapping
566
567     def wrapValue(self, type, instance):
568         if self.needsWrapping(type):
569             visitor = ValueWrapper()
570             visitor.visit(type, instance)
571
572     def unwrapValue(self, type, instance):
573         if self.needsWrapping(type):
574             visitor = ValueUnwrapper()
575             visitor.visit(type, instance)
576
577     def traceInterfaces(self, api):
578         interfaces = api.getAllInterfaces()
579         if not interfaces:
580             return
581         map(self.declareWrapperInterface, interfaces)
582         self.implementIidWrapper(api)
583         map(self.implementWrapperInterface, interfaces)
584         print
585
586     def declareWrapperInterface(self, interface):
587         print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
588         print "{"
589         print "private:"
590         print "    %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
591         print "    virtual ~%s();" % getWrapperInterfaceName(interface)
592         print "public:"
593         print "    static %s* _Create(const char *functionName, %s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
594         print
595         for method in interface.iterMethods():
596             print "    " + method.prototype() + ";"
597         print
598         #print "private:"
599         for type, name, value in self.enumWrapperInterfaceVariables(interface):
600             print '    %s %s;' % (type, name)
601         for i in range(64):
602             print r'    virtual void _dummy%i(void) const {' % i
603             print r'        os::log("error: %s: unexpected virtual method\n");' % interface.name
604             print r'        os::abort();'
605             print r'    }'
606         print "};"
607         print
608
609     def enumWrapperInterfaceVariables(self, interface):
610         return [
611             ("DWORD", "m_dwMagic", "0xd8365d6c"),
612             ("%s *" % interface.name, "m_pInstance", "pInstance"),
613             ("void *", "m_pVtbl", "*(void **)pInstance"),
614             ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
615         ] 
616
617     def implementWrapperInterface(self, interface):
618         self.interface = interface
619
620         # Private constructor
621         print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
622         for type, name, value in self.enumWrapperInterfaceVariables(interface):
623             print '    %s = %s;' % (name, value)
624         print '}'
625         print
626
627         # Public constructor
628         print '%s *%s::_Create(const char *functionName, %s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
629         print r'    std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pInstance);'
630         print r'    if (it != g_WrappedObjects.end()) {'
631         print r'        Wrap%s *pWrapper = (Wrap%s *)it->second;' % (interface.name, interface.name)
632         print r'        assert(pWrapper);'
633         print r'        assert(pWrapper->m_dwMagic == 0xd8365d6c);'
634         print r'        assert(pWrapper->m_pInstance == pInstance);'
635         print r'        if (pWrapper->m_pVtbl == *(void **)pInstance &&'
636         print r'            pWrapper->m_NumMethods >= %s) {' % len(list(interface.iterBaseMethods()))
637         print r'            //os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);'
638         print r'            return pWrapper;'
639         print r'        }'
640         print r'    }'
641         print r'    Wrap%s *pWrapper = new Wrap%s(pInstance);' % (interface.name, interface.name)
642         print r'    //os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);' % interface.name
643         print r'    g_WrappedObjects[pInstance] = pWrapper;'
644         print r'    return pWrapper;'
645         print '}'
646         print
647
648         # Destructor
649         print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
650         print r'        //os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", m_pInstance, this, m_pVtbl);' % interface.name
651         print r'        g_WrappedObjects.erase(m_pInstance);'
652         print '}'
653         print
654         
655         for base, method in interface.iterBaseMethods():
656             self.base = base
657             self.implementWrapperInterfaceMethod(interface, base, method)
658
659         print
660
661     def implementWrapperInterfaceMethod(self, interface, base, method):
662         print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
663
664         if False:
665             print r'    os::log("# %s #\n", __FUNCTION__);'
666
667         if method.type is not stdapi.Void:
668             print '    %s _result;' % method.type
669     
670         self.implementWrapperInterfaceMethodBody(interface, base, method)
671     
672         if method.type is not stdapi.Void:
673             print '    return _result;'
674         print '}'
675         print
676
677     def implementWrapperInterfaceMethodBody(self, interface, base, method):
678         assert not method.internal
679
680         print '    static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
681         print '    static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1)
682
683         print '    %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
684
685         print '    unsigned _call = trace::localWriter.beginEnter(&_sig);'
686         print '    trace::localWriter.beginArg(0);'
687         print '    trace::localWriter.writePointer((uintptr_t)m_pInstance);'
688         print '    trace::localWriter.endArg();'
689         for arg in method.args:
690             if not arg.output:
691                 self.unwrapArg(method, arg)
692                 self.serializeArg(method, arg)
693         print '    trace::localWriter.endEnter();'
694         
695         self.invokeMethod(interface, base, method)
696
697         print '    trace::localWriter.beginLeave(_call);'
698
699         print '    if (%s) {' % self.wasFunctionSuccessful(method)
700         for arg in method.args:
701             if arg.output:
702                 self.serializeArg(method, arg)
703                 self.wrapArg(method, arg)
704         print '    }'
705
706         if method.type is not stdapi.Void:
707             self.serializeRet(method, '_result')
708         if method.type is not stdapi.Void:
709             self.wrapRet(method, '_result')
710
711         if method.name == 'Release':
712             assert method.type is not stdapi.Void
713             print r'    if (!_result) {'
714             print r'        delete this;'
715             print r'    }'
716         
717         print '    trace::localWriter.endLeave();'
718
719     def implementIidWrapper(self, api):
720         print r'static void'
721         print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
722         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",'
723         print r'            functionName, reason,'
724         print r'            riid.Data1, riid.Data2, riid.Data3,'
725         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]);'
726         print r'}'
727         print 
728         print r'static void'
729         print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
730         print r'    if (!ppvObj || !*ppvObj) {'
731         print r'        return;'
732         print r'    }'
733         else_ = ''
734         for iface in api.getAllInterfaces():
735             print r'    %sif (riid == IID_%s) {' % (else_, iface.name)
736             print r'        *ppvObj = Wrap%s::_Create(functionName, (%s *) *ppvObj);' % (iface.name, iface.name)
737             print r'    }'
738             else_ = 'else '
739         print r'    %s{' % else_
740         print r'        warnIID(functionName, riid, "unknown");'
741         print r'    }'
742         print r'}'
743         print
744
745     def wrapIid(self, function, riid, out):
746         # Cast output arg to `void **` if necessary
747         out_name = out.name
748         obj_type = out.type.type.type
749         if not obj_type is stdapi.Void:
750             assert isinstance(obj_type, stdapi.Interface)
751             out_name = 'reinterpret_cast<void * *>(%s)' % out_name
752
753         print r'    if (%s && *%s) {' % (out.name, out.name)
754         functionName = function.name
755         else_ = ''
756         if self.interface is not None:
757             functionName = self.interface.name + '::' + functionName
758             print r'        if (*%s == m_pInstance &&' % (out_name,)
759             print r'            (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
760             print r'            *%s = this;' % (out_name,)
761             print r'        }'
762             else_ = 'else '
763         print r'        %s{' % else_
764         print r'             wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
765         print r'        }'
766         print r'    }'
767
768     def invokeMethod(self, interface, base, method):
769         if method.type is stdapi.Void:
770             result = ''
771         else:
772             result = '_result = '
773         print '    %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
774     
775     def emit_memcpy(self, dest, src, length):
776         print '        unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
777         print '        trace::localWriter.beginArg(0);'
778         print '        trace::localWriter.writePointer((uintptr_t)%s);' % dest
779         print '        trace::localWriter.endArg();'
780         print '        trace::localWriter.beginArg(1);'
781         print '        trace::localWriter.writeBlob(%s, %s);' % (src, length)
782         print '        trace::localWriter.endArg();'
783         print '        trace::localWriter.beginArg(2);'
784         print '        trace::localWriter.writeUInt(%s);' % length
785         print '        trace::localWriter.endArg();'
786         print '        trace::localWriter.endEnter();'
787         print '        trace::localWriter.beginLeave(_call);'
788         print '        trace::localWriter.endLeave();'
789     
790     def fake_call(self, function, args):
791         print '            unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
792         for arg, instance in zip(function.args, args):
793             assert not arg.output
794             print '            trace::localWriter.beginArg(%u);' % (arg.index,)
795             self.serializeValue(arg.type, instance)
796             print '            trace::localWriter.endArg();'
797         print '            trace::localWriter.endEnter();'
798         print '            trace::localWriter.beginLeave(_fake_call);'
799         print '            trace::localWriter.endLeave();'
800