1 ##########################################################################
3 # Copyright 2008-2010 VMware, Inc.
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:
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the Software.
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
24 ##########################################################################/
26 """Common trace code generation."""
32 sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
35 import specs.stdapi as stdapi
38 def getWrapperInterfaceName(interface):
39 return "Wrap" + interface.expr
43 class ComplexValueSerializer(stdapi.OnceVisitor):
44 '''Type visitors which generates serialization functions for
47 Simple types are serialized inline.
50 def __init__(self, serializer):
51 stdapi.OnceVisitor.__init__(self)
52 self.serializer = serializer
54 def visitVoid(self, literal):
57 def visitLiteral(self, literal):
60 def visitString(self, string):
63 def visitConst(self, const):
64 self.visit(const.type)
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:
72 print ' "%s",' % (name,)
74 print 'static const trace::StructSig _struct%s_sig = {' % (struct.tag,)
75 if struct.name is None:
78 structName = '"%s"' % struct.name
79 print ' %u, %s, %u, _struct%s_members' % (struct.id, structName, len(struct.members), struct.tag)
83 def visitArray(self, array):
84 self.visit(array.type)
86 def visitBlob(self, array):
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)
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)
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)
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)
111 def visitPointer(self, pointer):
112 self.visit(pointer.type)
114 def visitIntPointer(self, pointer):
117 def visitObjPointer(self, pointer):
118 self.visit(pointer.type)
120 def visitLinearPointer(self, pointer):
121 self.visit(pointer.type)
123 def visitHandle(self, handle):
124 self.visit(handle.type)
126 def visitReference(self, reference):
127 self.visit(reference.type)
129 def visitAlias(self, alias):
130 self.visit(alias.type)
132 def visitOpaque(self, opaque):
135 def visitInterface(self, interface):
138 def visitPolymorphic(self, polymorphic):
139 if not polymorphic.contextLess:
141 print 'static void _write__%s(int selector, %s const & value) {' % (polymorphic.tag, polymorphic.expr)
142 print ' switch (selector) {'
143 for cases, type in polymorphic.iterSwitch():
146 self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
153 class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
154 '''Visitor which generates code to serialize any type.
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.
161 def visitLiteral(self, literal, instance):
162 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
164 def visitString(self, string, instance):
166 cast = 'const char *'
169 cast = 'const wchar_t *'
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)
178 print ' trace::localWriter.write%s(%s%s);' % (suffix, instance, length)
180 def visitConst(self, const, instance):
181 self.visit(const.type, instance)
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();'
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();'
201 print ' trace::localWriter.endArray();'
203 print ' trace::localWriter.writeNull();'
206 def visitBlob(self, blob, instance):
207 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
209 def visitEnum(self, enum, instance):
210 print ' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
212 def visitBitmask(self, bitmask, instance):
213 print ' trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
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();'
223 print ' trace::localWriter.writeNull();'
226 def visitIntPointer(self, pointer, instance):
227 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
229 def visitObjPointer(self, pointer, instance):
230 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
232 def visitLinearPointer(self, pointer, instance):
233 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
235 def visitReference(self, reference, instance):
236 self.visit(reference.type, instance)
238 def visitHandle(self, handle, instance):
239 self.visit(handle.type, instance)
241 def visitAlias(self, alias, instance):
242 self.visit(alias.type, instance)
244 def visitOpaque(self, opaque, instance):
245 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
247 def visitInterface(self, interface, instance):
250 def visitPolymorphic(self, polymorphic, instance):
251 if polymorphic.contextLess:
252 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
254 switchExpr = self.expand(polymorphic.switchExpr)
255 print ' switch (%s) {' % switchExpr
256 for cases, type in polymorphic.iterSwitch():
259 caseInstance = instance
260 if type.expr is not None:
261 caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
262 self.visit(type, caseInstance)
264 if polymorphic.defaultType is None:
266 print r' os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,)
267 print r' trace::localWriter.writeNull();'
272 class WrapDecider(stdapi.Traverser):
273 '''Type visitor which will decide wheter this type will need wrapping or not.
275 For complex types (arrays, structures), we need to know this before hand.
279 self.needsWrapping = False
281 def visitLinearPointer(self, void):
284 def visitInterface(self, interface):
285 self.needsWrapping = True
288 class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
289 '''Type visitor which will generate the code to wrap an instance.
291 Wrapping is necessary mostly for interfaces, however interface pointers can
292 appear anywhere inside complex types.
295 def visitStruct(self, struct, instance):
296 for member in struct.members:
297 self.visitMember(member, instance)
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]")
307 def visitPointer(self, pointer, instance):
308 print " if (%s) {" % instance
309 self.visit(pointer.type, "*" + instance)
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)
319 self.visitPointer(pointer, instance)
321 def visitInterface(self, interface, instance):
322 raise NotImplementedError
324 def visitInterfacePointer(self, interface, instance):
325 print " if (%s) {" % instance
326 print " %s = %s::_Create(__FUNCTION__, %s);" % (instance, getWrapperInterfaceName(interface), instance)
329 def visitPolymorphic(self, type, instance):
330 # XXX: There might be polymorphic values that need wrapping in the future
331 raise NotImplementedError
334 class ValueUnwrapper(ValueWrapper):
335 '''Reverse of ValueWrapper.'''
339 def visitStruct(self, struct, instance):
340 if not self.allocated:
341 # Argument is constant. We need to create a non const
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:],)
348 self.allocated = True
350 return ValueWrapper.visitStruct(self, struct, instance)
354 return ValueWrapper.visitStruct(self, struct, instance)
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]")
368 print " %s = _t;" % instance
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,)
377 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
383 '''Base class to orchestrate the code generation of API tracing.'''
385 # 0-3 are reserved to memcpy, malloc, free, and realloc
391 def serializerFactory(self):
392 '''Create a serializer.
394 Can be overriden by derived classes to inject their own serialzer.
397 return ValueSerializer()
399 def traceApi(self, api):
405 for module in api.modules:
406 for header in module.headers:
410 # Generate the serializer functions
411 types = api.getAllTypes()
412 visitor = ComplexValueSerializer(self.serializerFactory())
413 map(visitor.visit, types)
417 self.traceInterfaces(api)
420 self.interface = None
422 for function in api.getAllFunctions():
423 self.traceFunctionDecl(function)
424 for function in api.getAllFunctions():
425 self.traceFunctionImpl(function)
430 def header(self, api):
431 print '#ifdef _WIN32'
432 print '# include <malloc.h> // alloca'
433 print '# ifndef alloca'
434 print '# define alloca _alloca'
437 print '# include <alloca.h> // alloca'
440 print '#include "trace.hpp"'
442 print 'static std::map<void *, void *> g_WrappedObjects;'
444 def footer(self, api):
447 def traceFunctionDecl(self, function):
448 # Per-function declarations
450 if not function.internal:
452 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
454 print 'static const char ** _%s_args = NULL;' % (function.name,)
455 print 'static const trace::FunctionSig _%s_sig = {%u, "%s", %u, _%s_args};' % (function.name, self.getFunctionSigId(), function.name, len(function.args), function.name)
458 def getFunctionSigId(self):
463 def isFunctionPublic(self, function):
466 def traceFunctionImpl(self, function):
467 if self.isFunctionPublic(function):
468 print 'extern "C" PUBLIC'
470 print 'extern "C" PRIVATE'
471 print function.prototype() + ' {'
472 if function.type is not stdapi.Void:
473 print ' %s _result;' % function.type
475 # No-op if tracing is disabled
476 print ' if (!trace::isTracingEnabled()) {'
477 Tracer.invokeFunction(self, function)
478 if function.type is not stdapi.Void:
479 print ' return _result;'
484 self.traceFunctionImplBody(function)
485 if function.type is not stdapi.Void:
486 print ' return _result;'
490 def traceFunctionImplBody(self, function):
491 if not function.internal:
492 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
493 for arg in function.args:
495 self.unwrapArg(function, arg)
496 for arg in function.args:
498 self.serializeArg(function, arg)
499 print ' trace::localWriter.endEnter();'
500 self.invokeFunction(function)
501 if not function.internal:
502 print ' trace::localWriter.beginLeave(_call);'
503 print ' if (%s) {' % self.wasFunctionSuccessful(function)
504 for arg in function.args:
506 self.serializeArg(function, arg)
507 self.wrapArg(function, arg)
509 if function.type is not stdapi.Void:
510 self.serializeRet(function, "_result")
511 if function.type is not stdapi.Void:
512 self.wrapRet(function, "_result")
513 print ' trace::localWriter.endLeave();'
515 def invokeFunction(self, function, prefix='_', suffix=''):
516 if function.type is stdapi.Void:
519 result = '_result = '
520 dispatch = prefix + function.name + suffix
521 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
523 def wasFunctionSuccessful(self, function):
524 if function.type is stdapi.Void:
526 if str(function.type) == 'HRESULT':
527 return 'SUCCEEDED(_result)'
530 def serializeArg(self, function, arg):
531 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
532 self.serializeArgValue(function, arg)
533 print ' trace::localWriter.endArg();'
535 def serializeArgValue(self, function, arg):
536 self.serializeValue(arg.type, arg.name)
538 def wrapArg(self, function, arg):
539 assert not isinstance(arg.type, stdapi.ObjPointer)
541 from specs.winapi import REFIID
543 for other_arg in function.args:
544 if not other_arg.output and other_arg.type is REFIID:
546 if riid is not None \
547 and isinstance(arg.type, stdapi.Pointer) \
548 and isinstance(arg.type.type, stdapi.ObjPointer):
549 self.wrapIid(function, riid, arg)
552 self.wrapValue(arg.type, arg.name)
554 def unwrapArg(self, function, arg):
555 self.unwrapValue(arg.type, arg.name)
557 def serializeRet(self, function, instance):
558 print ' trace::localWriter.beginReturn();'
559 self.serializeValue(function.type, instance)
560 print ' trace::localWriter.endReturn();'
562 def serializeValue(self, type, instance):
563 serializer = self.serializerFactory()
564 serializer.visit(type, instance)
566 def wrapRet(self, function, instance):
567 self.wrapValue(function.type, instance)
569 def needsWrapping(self, type):
570 visitor = WrapDecider()
572 return visitor.needsWrapping
574 def wrapValue(self, type, instance):
575 if self.needsWrapping(type):
576 visitor = ValueWrapper()
577 visitor.visit(type, instance)
579 def unwrapValue(self, type, instance):
580 if self.needsWrapping(type):
581 visitor = ValueUnwrapper()
582 visitor.visit(type, instance)
584 def traceInterfaces(self, api):
585 interfaces = api.getAllInterfaces()
588 map(self.declareWrapperInterface, interfaces)
589 self.implementIidWrapper(api)
590 map(self.implementWrapperInterface, interfaces)
593 def declareWrapperInterface(self, interface):
594 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
597 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
598 print " virtual ~%s();" % getWrapperInterfaceName(interface)
600 print " static %s* _Create(const char *functionName, %s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
602 for method in interface.iterMethods():
603 print " " + method.prototype() + ";"
606 for type, name, value in self.enumWrapperInterfaceVariables(interface):
607 print ' %s %s;' % (type, name)
609 print r' virtual void _dummy%i(void) const {' % i
610 print r' os::log("error: %s: unexpected virtual method\n");' % interface.name
611 print r' os::abort();'
616 def enumWrapperInterfaceVariables(self, interface):
618 ("DWORD", "m_dwMagic", "0xd8365d6c"),
619 ("%s *" % interface.name, "m_pInstance", "pInstance"),
620 ("void *", "m_pVtbl", "*(void **)pInstance"),
621 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
624 def implementWrapperInterface(self, interface):
625 self.interface = interface
627 # Private constructor
628 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
629 for type, name, value in self.enumWrapperInterfaceVariables(interface):
630 print ' %s = %s;' % (name, value)
635 print '%s *%s::_Create(const char *functionName, %s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
636 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pInstance);'
637 print r' if (it != g_WrappedObjects.end()) {'
638 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (interface.name, interface.name)
639 print r' assert(pWrapper);'
640 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
641 print r' assert(pWrapper->m_pInstance == pInstance);'
642 print r' if (pWrapper->m_pVtbl == *(void **)pInstance &&'
643 print r' pWrapper->m_NumMethods >= %s) {' % len(list(interface.iterBaseMethods()))
644 #print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);'
645 print r' return pWrapper;'
648 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (interface.name, interface.name)
649 #print r' os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);' % interface.name
650 print r' g_WrappedObjects[pInstance] = pWrapper;'
651 print r' return pWrapper;'
656 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
657 #print r' os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", m_pInstance, this, m_pVtbl);' % interface.name
658 print r' g_WrappedObjects.erase(m_pInstance);'
662 for base, method in interface.iterBaseMethods():
664 self.implementWrapperInterfaceMethod(interface, base, method)
668 def implementWrapperInterfaceMethod(self, interface, base, method):
669 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
672 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (getWrapperInterfaceName(interface) + '::' + method.name)
674 if method.type is not stdapi.Void:
675 print ' %s _result;' % method.type
677 self.implementWrapperInterfaceMethodBody(interface, base, method)
679 if method.type is not stdapi.Void:
680 print ' return _result;'
684 def implementWrapperInterfaceMethodBody(self, interface, base, method):
685 assert not method.internal
687 print ' static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
688 print ' static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (self.getFunctionSigId(), interface.name + '::' + method.name, len(method.args) + 1)
690 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
692 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
693 print ' trace::localWriter.beginArg(0);'
694 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
695 print ' trace::localWriter.endArg();'
696 for arg in method.args:
698 self.unwrapArg(method, arg)
699 for arg in method.args:
701 self.serializeArg(method, arg)
702 print ' trace::localWriter.endEnter();'
704 self.invokeMethod(interface, base, method)
706 print ' trace::localWriter.beginLeave(_call);'
708 print ' if (%s) {' % self.wasFunctionSuccessful(method)
709 for arg in method.args:
711 self.serializeArg(method, arg)
712 self.wrapArg(method, arg)
715 if method.type is not stdapi.Void:
716 self.serializeRet(method, '_result')
717 if method.type is not stdapi.Void:
718 self.wrapRet(method, '_result')
720 if method.name == 'Release':
721 assert method.type is not stdapi.Void
722 print r' if (!_result) {'
723 print r' delete this;'
726 print ' trace::localWriter.endLeave();'
728 def implementIidWrapper(self, api):
730 print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
731 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",'
732 print r' functionName, reason,'
733 print r' riid.Data1, riid.Data2, riid.Data3,'
734 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]);'
738 print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
739 print r' if (!ppvObj || !*ppvObj) {'
743 for iface in api.getAllInterfaces():
744 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
745 print r' *ppvObj = Wrap%s::_Create(functionName, (%s *) *ppvObj);' % (iface.name, iface.name)
748 print r' %s{' % else_
749 print r' warnIID(functionName, riid, "unknown");'
754 def wrapIid(self, function, riid, out):
755 # Cast output arg to `void **` if necessary
757 obj_type = out.type.type.type
758 if not obj_type is stdapi.Void:
759 assert isinstance(obj_type, stdapi.Interface)
760 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
762 print r' if (%s && *%s) {' % (out.name, out.name)
763 functionName = function.name
765 if self.interface is not None:
766 functionName = self.interface.name + '::' + functionName
767 print r' if (*%s == m_pInstance &&' % (out_name,)
768 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
769 print r' *%s = this;' % (out_name,)
772 print r' %s{' % else_
773 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
777 def invokeMethod(self, interface, base, method):
778 if method.type is stdapi.Void:
781 result = '_result = '
782 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
784 def emit_memcpy(self, dest, src, length):
785 print ' unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig, true);'
786 print ' trace::localWriter.beginArg(0);'
787 print ' trace::localWriter.writePointer((uintptr_t)%s);' % dest
788 print ' trace::localWriter.endArg();'
789 print ' trace::localWriter.beginArg(1);'
790 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
791 print ' trace::localWriter.endArg();'
792 print ' trace::localWriter.beginArg(2);'
793 print ' trace::localWriter.writeUInt(%s);' % length
794 print ' trace::localWriter.endArg();'
795 print ' trace::localWriter.endEnter();'
796 print ' trace::localWriter.beginLeave(_call);'
797 print ' trace::localWriter.endLeave();'
799 def fake_call(self, function, args):
800 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
801 for arg, instance in zip(function.args, args):
802 assert not arg.output
803 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
804 self.serializeValue(arg.type, instance)
805 print ' trace::localWriter.endArg();'
806 print ' trace::localWriter.endEnter();'
807 print ' trace::localWriter.beginLeave(_fake_call);'
808 print ' trace::localWriter.endLeave();'