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