]> git.cworth.org Git - apitrace/blob - wrappers/trace.py
Merge remote-tracking branch 'github/master' into d2d
[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 class ComplexValueSerializer(stdapi.OnceVisitor):
43     '''Type visitors which generates serialization functions for
44     complex types.
45     
46     Simple types are serialized inline.
47     '''
48
49     def __init__(self, serializer):
50         stdapi.OnceVisitor.__init__(self)
51         self.serializer = serializer
52
53     def visitVoid(self, literal):
54         pass
55
56     def visitLiteral(self, literal):
57         pass
58
59     def visitString(self, string):
60         pass
61
62     def visitConst(self, const):
63         self.visit(const.type)
64
65     def visitStruct(self, struct):
66         for type, name in struct.members:
67             self.visit(type)
68         print 'static void _write__%s(const %s &value) {' % (struct.tag, struct.expr)
69         print '    static const char * members[%u] = {' % (len(struct.members),)
70         for type, name,  in struct.members:
71             print '        "%s",' % (name,)
72         print '    };'
73         print '    static const trace::StructSig sig = {'
74         print '       %u, "%s", %u, members' % (struct.id, struct.name, len(struct.members))
75         print '    };'
76         print '    trace::localWriter.beginStruct(&sig);'
77         for type, name in struct.members:
78             self.serializer.visit(type, 'value.%s' % (name,))
79         print '    trace::localWriter.endStruct();'
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):
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' % 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 '    _write__%s(%s);' % (struct.tag, instance)
185
186     def visitArray(self, array, instance):
187         length = '_c' + array.type.tag
188         index = '_i' + array.type.tag
189         print '    if (%s) {' % instance
190         print '        size_t %s = %s > 0 ? %s : 0;' % (length, array.length, array.length)
191         print '        trace::localWriter.beginArray(%s);' % length
192         print '        for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
193         print '            trace::localWriter.beginElement();'
194         self.visit(array.type, '(%s)[%s]' % (instance, index))
195         print '            trace::localWriter.endElement();'
196         print '        }'
197         print '        trace::localWriter.endArray();'
198         print '    } else {'
199         print '        trace::localWriter.writeNull();'
200         print '    }'
201
202     def visitBlob(self, blob, instance):
203         print '    trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size)
204
205     def visitEnum(self, enum, instance):
206         print '    trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
207
208     def visitBitmask(self, bitmask, instance):
209         print '    trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
210
211     def visitPointer(self, pointer, instance):
212         print '    if (%s) {' % instance
213         print '        trace::localWriter.beginArray(1);'
214         print '        trace::localWriter.beginElement();'
215         self.visit(pointer.type, "*" + instance)
216         print '        trace::localWriter.endElement();'
217         print '        trace::localWriter.endArray();'
218         print '    } else {'
219         print '        trace::localWriter.writeNull();'
220         print '    }'
221
222     def visitIntPointer(self, pointer, instance):
223         print '    trace::localWriter.writePointer((uintptr_t)%s);' % instance
224
225     def visitObjPointer(self, pointer, instance):
226         print '    trace::localWriter.writePointer((uintptr_t)%s);' % instance
227
228     def visitLinearPointer(self, pointer, instance):
229         print '    trace::localWriter.writePointer((uintptr_t)%s);' % instance
230
231     def visitReference(self, reference, instance):
232         self.visit(reference.type, instance)
233
234     def visitHandle(self, handle, instance):
235         self.visit(handle.type, instance)
236
237     def visitAlias(self, alias, instance):
238         self.visit(alias.type, instance)
239
240     def visitOpaque(self, opaque, instance):
241         print '    trace::localWriter.writePointer((uintptr_t)%s);' % instance
242
243     def visitInterface(self, interface, instance):
244         assert False
245
246     def visitPolymorphic(self, polymorphic, instance):
247         if polymorphic.contextLess:
248             print '    _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
249         else:
250             print '    switch (%s) {' % polymorphic.switchExpr
251             for cases, type in polymorphic.iterSwitch():
252                 for case in cases:
253                     print '    %s:' % case
254                 self.visit(type, 'static_cast<%s>(%s)' % (type, instance))
255                 print '        break;'
256             print '    }'
257
258
259 class WrapDecider(stdapi.Traverser):
260     '''Type visitor which will decide wheter this type will need wrapping or not.
261     
262     For complex types (arrays, structures), we need to know this before hand.
263     '''
264
265     def __init__(self):
266         self.needsWrapping = False
267
268     def visitLinearPointer(self, void):
269         pass
270
271     def visitInterface(self, interface):
272         self.needsWrapping = True
273
274
275 class ValueWrapper(stdapi.Traverser):
276     '''Type visitor which will generate the code to wrap an instance.
277     
278     Wrapping is necessary mostly for interfaces, however interface pointers can
279     appear anywhere inside complex types.
280     '''
281
282     def visitStruct(self, struct, instance):
283         for type, name in struct.members:
284             self.visit(type, "(%s).%s" % (instance, name))
285
286     def visitArray(self, array, instance):
287         print "    if (%s) {" % instance
288         print "        for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array.length
289         self.visit(array.type, instance + "[_i]")
290         print "        }"
291         print "    }"
292
293     def visitPointer(self, pointer, instance):
294         print "    if (%s) {" % instance
295         self.visit(pointer.type, "*" + instance)
296         print "    }"
297     
298     def visitObjPointer(self, pointer, instance):
299         elem_type = pointer.type.mutable()
300         if isinstance(elem_type, stdapi.Interface):
301             self.visitInterfacePointer(elem_type, instance)
302         elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
303             self.visitInterfacePointer(elem_type.type, instance)
304         else:
305             self.visitPointer(pointer, instance)
306     
307     def visitInterface(self, interface, instance):
308         raise NotImplementedError
309
310     def visitInterfacePointer(self, interface, instance):
311         print "    if (%s) {" % instance
312         print "        %s = new %s(%s);" % (instance, getWrapperInterfaceName(interface), instance)
313         print "    }"
314     
315     def visitPolymorphic(self, type, instance):
316         # XXX: There might be polymorphic values that need wrapping in the future
317         raise NotImplementedError
318
319
320 class ValueUnwrapper(ValueWrapper):
321     '''Reverse of ValueWrapper.'''
322
323     allocated = False
324
325     def visitStruct(self, struct, instance):
326         if not self.allocated:
327             # Argument is constant. We need to create a non const
328             print '    {'
329             print "        %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct)
330             print '        *_t = %s;' % (instance,)
331             assert instance.startswith('*')
332             print '        %s = _t;' % (instance[1:],)
333             instance = '*_t'
334             self.allocated = True
335             try:
336                 return ValueWrapper.visitStruct(self, struct, instance)
337             finally:
338                 print '    }'
339         else:
340             return ValueWrapper.visitStruct(self, struct, instance)
341
342     def visitArray(self, array, instance):
343         if self.allocated or isinstance(instance, stdapi.Interface):
344             return ValueWrapper.visitArray(self, array, instance)
345         elem_type = array.type.mutable()
346         print "    if (%s && %s) {" % (instance, array.length)
347         print "        %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array.length)
348         print "        for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array.length
349         print "            _t[_i] = %s[_i];" % instance 
350         self.allocated = True
351         self.visit(array.type, "_t[_i]")
352         print "        }"
353         print "        %s = _t;" % instance
354         print "    }"
355
356     def visitInterfacePointer(self, interface, instance):
357         print r'    if (%s) {' % instance
358         print r'        const %s *pWrapper = static_cast<const %s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
359         print r'        if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
360         print r'            %s = pWrapper->m_pInstance;' % (instance,)
361         print r'        } else {'
362         print r'            os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
363         print r'        }'
364         print r'    }'
365
366
367 class Tracer:
368     '''Base class to orchestrate the code generation of API tracing.'''
369
370     def __init__(self):
371         self.api = None
372
373     def serializerFactory(self):
374         '''Create a serializer.
375         
376         Can be overriden by derived classes to inject their own serialzer.
377         '''
378
379         return ValueSerializer()
380
381     def traceApi(self, api):
382         self.api = api
383
384         self.header(api)
385
386         # Includes
387         for header in api.headers:
388             print header
389         print
390
391         # Generate the serializer functions
392         types = api.getAllTypes()
393         visitor = ComplexValueSerializer(self.serializerFactory())
394         map(visitor.visit, types)
395         print
396
397         # Interfaces wrapers
398         self.traceInterfaces(api)
399
400         # Function wrappers
401         self.interface = None
402         self.base = None
403         map(self.traceFunctionDecl, api.functions)
404         map(self.traceFunctionImpl, api.functions)
405         print
406
407         self.footer(api)
408
409     def header(self, api):
410         print '#ifdef _WIN32'
411         print '#  include <malloc.h> // alloca'
412         print '#  ifndef alloca'
413         print '#    define alloca _alloca'
414         print '#  endif'
415         print '#else'
416         print '#  include <alloca.h> // alloca'
417         print '#endif'
418         print
419         print '#include "trace.hpp"'
420         print
421
422     def footer(self, api):
423         pass
424
425     def traceFunctionDecl(self, function):
426         # Per-function declarations
427
428         if not function.internal:
429             if function.args:
430                 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
431             else:
432                 print 'static const char ** _%s_args = NULL;' % (function.name,)
433             print 'static const trace::FunctionSig _%s_sig = {%u, "%s", %u, _%s_args};' % (function.name, function.id, function.name, len(function.args), function.name)
434             print
435
436     def isFunctionPublic(self, function):
437         return True
438
439     def traceFunctionImpl(self, function):
440         if self.isFunctionPublic(function):
441             print 'extern "C" PUBLIC'
442         else:
443             print 'extern "C" PRIVATE'
444         print function.prototype() + ' {'
445         if function.type is not stdapi.Void:
446             print '    %s _result;' % function.type
447
448         # No-op if tracing is disabled
449         print '    if (!trace::isTracingEnabled()) {'
450         Tracer.invokeFunction(self, function)
451         if function.type is not stdapi.Void:
452             print '        return _result;'
453         else:
454             print '        return;'
455         print '    }'
456
457         self.traceFunctionImplBody(function)
458         if function.type is not stdapi.Void:
459             print '    return _result;'
460         print '}'
461         print
462
463     def traceFunctionImplBody(self, function):
464         if not function.internal:
465             print '    unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
466             for arg in function.args:
467                 if not arg.output:
468                     self.unwrapArg(function, arg)
469                     self.serializeArg(function, arg)
470             print '    trace::localWriter.endEnter();'
471         self.invokeFunction(function)
472         if not function.internal:
473             print '    trace::localWriter.beginLeave(_call);'
474             for arg in function.args:
475                 if arg.output:
476                     self.serializeArg(function, arg)
477                     self.wrapArg(function, arg)
478             if function.type is not stdapi.Void:
479                 self.serializeRet(function, "_result")
480             print '    trace::localWriter.endLeave();'
481             if function.type is not stdapi.Void:
482                 self.wrapRet(function, "_result")
483
484     def invokeFunction(self, function, prefix='_', suffix=''):
485         if function.type is stdapi.Void:
486             result = ''
487         else:
488             result = '_result = '
489         dispatch = prefix + function.name + suffix
490         print '    %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
491
492     def serializeArg(self, function, arg):
493         print '    trace::localWriter.beginArg(%u);' % (arg.index,)
494         self.serializeArgValue(function, arg)
495         print '    trace::localWriter.endArg();'
496
497     def serializeArgValue(self, function, arg):
498         self.serializeValue(arg.type, arg.name)
499
500     def wrapArg(self, function, arg):
501         assert not isinstance(arg.type, stdapi.ObjPointer)
502
503         from specs.winapi import REFIID
504         riid = None
505         for other_arg in function.args:
506             if not other_arg.output and other_arg.type is REFIID:
507                 riid = other_arg
508         if riid is not None \
509            and isinstance(arg.type, stdapi.Pointer) \
510            and isinstance(arg.type.type, stdapi.ObjPointer):
511             self.wrapIid(function, riid, arg)
512             return
513
514         self.wrapValue(arg.type, arg.name)
515
516     def unwrapArg(self, function, arg):
517         self.unwrapValue(arg.type, arg.name)
518
519     def serializeRet(self, function, instance):
520         print '    trace::localWriter.beginReturn();'
521         self.serializeValue(function.type, instance)
522         print '    trace::localWriter.endReturn();'
523
524     def serializeValue(self, type, instance):
525         serializer = self.serializerFactory()
526         serializer.visit(type, instance)
527
528     def wrapRet(self, function, instance):
529         self.wrapValue(function.type, instance)
530
531     def unwrapRet(self, function, instance):
532         self.unwrapValue(function.type, instance)
533
534     def needsWrapping(self, type):
535         visitor = WrapDecider()
536         visitor.visit(type)
537         return visitor.needsWrapping
538
539     def wrapValue(self, type, instance):
540         if self.needsWrapping(type):
541             visitor = ValueWrapper()
542             visitor.visit(type, instance)
543
544     def unwrapValue(self, type, instance):
545         if self.needsWrapping(type):
546             visitor = ValueUnwrapper()
547             visitor.visit(type, instance)
548
549     def traceInterfaces(self, api):
550         interfaces = api.getAllInterfaces()
551         if not interfaces:
552             return
553         map(self.declareWrapperInterface, interfaces)
554         self.implementIidWrapper(api)
555         map(self.implementWrapperInterface, interfaces)
556         print
557
558     def declareWrapperInterface(self, interface):
559         print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
560         print "{"
561         print "public:"
562         print "    %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
563         print "    virtual ~%s();" % getWrapperInterfaceName(interface)
564         print
565         for method in interface.iterMethods():
566             print "    " + method.prototype() + ";"
567         print
568         #print "private:"
569         for type, name, value in self.enumWrapperInterfaceVariables(interface):
570             print '    %s %s;' % (type, name)
571         print "};"
572         print
573
574     def enumWrapperInterfaceVariables(self, interface):
575         return [
576             ("DWORD", "m_dwMagic", "0xd8365d6c"),
577             ("%s *" % interface.name, "m_pInstance", "pInstance"),
578         ] 
579
580     def implementWrapperInterface(self, interface):
581         self.interface = interface
582
583         print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
584         for type, name, value in self.enumWrapperInterfaceVariables(interface):
585             print '    %s = %s;' % (name, value)
586         print '}'
587         print
588         print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
589         print '}'
590         print
591         
592         for base, method in interface.iterBaseMethods():
593             self.base = base
594             self.implementWrapperInterfaceMethod(interface, base, method)
595
596         print
597
598     def implementWrapperInterfaceMethod(self, interface, base, method):
599         print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
600         if method.type is not stdapi.Void:
601             print '    %s _result;' % method.type
602     
603         self.implementWrapperInterfaceMethodBody(interface, base, method)
604     
605         if method.type is not stdapi.Void:
606             print '    return _result;'
607         print '}'
608         print
609
610     def implementWrapperInterfaceMethodBody(self, interface, base, method):
611         assert not method.internal
612
613         print '    static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
614         print '    static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1)
615
616         print '    %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
617
618         print '    unsigned _call = trace::localWriter.beginEnter(&_sig);'
619         print '    trace::localWriter.beginArg(0);'
620         print '    trace::localWriter.writePointer((uintptr_t)m_pInstance);'
621         print '    trace::localWriter.endArg();'
622         for arg in method.args:
623             if not arg.output:
624                 self.unwrapArg(method, arg)
625                 self.serializeArg(method, arg)
626         print '    trace::localWriter.endEnter();'
627         
628         self.invokeMethod(interface, base, method)
629
630         print '    trace::localWriter.beginLeave(_call);'
631         for arg in method.args:
632             if arg.output:
633                 self.serializeArg(method, arg)
634                 self.wrapArg(method, arg)
635
636         if method.type is not stdapi.Void:
637             self.serializeRet(method, '_result')
638         print '    trace::localWriter.endLeave();'
639         if method.type is not stdapi.Void:
640             self.wrapRet(method, '_result')
641
642         if method.name == 'Release':
643             assert method.type is not stdapi.Void
644             print '    if (!_result)'
645             print '        delete this;'
646
647     def implementIidWrapper(self, api):
648         print r'static void'
649         print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
650         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",'
651         print r'            functionName, reason,'
652         print r'            riid.Data1, riid.Data2, riid.Data3,'
653         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]);'
654         print r'}'
655         print 
656         print r'static void'
657         print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
658         print r'    if (!ppvObj || !*ppvObj) {'
659         print r'        return;'
660         print r'    }'
661         else_ = ''
662         for iface in api.getAllInterfaces():
663             print r'    %sif (riid == IID_%s) {' % (else_, iface.name)
664             print r'        *ppvObj = new Wrap%s((%s *) *ppvObj);' % (iface.name, iface.name)
665             print r'    }'
666             else_ = 'else '
667         print r'    %s{' % else_
668         print r'        warnIID(functionName, riid, "unknown");'
669         print r'    }'
670         print r'}'
671         print
672
673     def wrapIid(self, function, riid, out):
674         # Cast output arg to `void **` if necessary
675         out_name = out.name
676         obj_type = out.type.type.type
677         if not obj_type is stdapi.Void:
678             assert isinstance(obj_type, stdapi.Interface)
679             out_name = 'reinterpret_cast<void * *>(%s)' % out_name
680
681         print r'    if (%s && *%s) {' % (out.name, out.name)
682         functionName = function.name
683         else_ = ''
684         if self.interface is not None:
685             functionName = self.interface.name + '::' + functionName
686             print r'        if (*%s == m_pInstance &&' % (out_name,)
687             print r'            (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
688             print r'            *%s = this;' % (out_name,)
689             print r'        }'
690             else_ = 'else '
691         print r'        %s{' % else_
692         print r'             wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
693         print r'        }'
694         print r'    }'
695
696     def invokeMethod(self, interface, base, method):
697         if method.type is stdapi.Void:
698             result = ''
699         else:
700             result = '_result = '
701         print '    %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
702     
703     def emit_memcpy(self, dest, src, length):
704         print '        unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
705         print '        trace::localWriter.beginArg(0);'
706         print '        trace::localWriter.writePointer((uintptr_t)%s);' % dest
707         print '        trace::localWriter.endArg();'
708         print '        trace::localWriter.beginArg(1);'
709         print '        trace::localWriter.writeBlob(%s, %s);' % (src, length)
710         print '        trace::localWriter.endArg();'
711         print '        trace::localWriter.beginArg(2);'
712         print '        trace::localWriter.writeUInt(%s);' % length
713         print '        trace::localWriter.endArg();'
714         print '        trace::localWriter.endEnter();'
715         print '        trace::localWriter.beginLeave(_call);'
716         print '        trace::localWriter.endLeave();'
717     
718     def fake_call(self, function, args):
719         print '            unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
720         for arg, instance in zip(function.args, args):
721             assert not arg.output
722             print '            trace::localWriter.beginArg(%u);' % (arg.index,)
723             self.serializeValue(arg.type, instance)
724             print '            trace::localWriter.endArg();'
725         print '            trace::localWriter.endEnter();'
726         print '            trace::localWriter.beginLeave(_fake_call);'
727         print '            trace::localWriter.endLeave();'
728