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, const %s & 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 self.serializeArg(function, arg)
497 print ' trace::localWriter.endEnter();'
498 self.invokeFunction(function)
499 if not function.internal:
500 print ' trace::localWriter.beginLeave(_call);'
501 print ' if (%s) {' % self.wasFunctionSuccessful(function)
502 for arg in function.args:
504 self.serializeArg(function, arg)
505 self.wrapArg(function, arg)
507 if function.type is not stdapi.Void:
508 self.serializeRet(function, "_result")
509 if function.type is not stdapi.Void:
510 self.wrapRet(function, "_result")
511 print ' trace::localWriter.endLeave();'
513 def invokeFunction(self, function, prefix='_', suffix=''):
514 if function.type is stdapi.Void:
517 result = '_result = '
518 dispatch = prefix + function.name + suffix
519 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
521 def wasFunctionSuccessful(self, function):
522 if function.type is stdapi.Void:
524 if str(function.type) == 'HRESULT':
525 return 'SUCCEEDED(_result)'
528 def serializeArg(self, function, arg):
529 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
530 self.serializeArgValue(function, arg)
531 print ' trace::localWriter.endArg();'
533 def serializeArgValue(self, function, arg):
534 self.serializeValue(arg.type, arg.name)
536 def wrapArg(self, function, arg):
537 assert not isinstance(arg.type, stdapi.ObjPointer)
539 from specs.winapi import REFIID
541 for other_arg in function.args:
542 if not other_arg.output and other_arg.type is REFIID:
544 if riid is not None \
545 and isinstance(arg.type, stdapi.Pointer) \
546 and isinstance(arg.type.type, stdapi.ObjPointer):
547 self.wrapIid(function, riid, arg)
550 self.wrapValue(arg.type, arg.name)
552 def unwrapArg(self, function, arg):
553 self.unwrapValue(arg.type, arg.name)
555 def serializeRet(self, function, instance):
556 print ' trace::localWriter.beginReturn();'
557 self.serializeValue(function.type, instance)
558 print ' trace::localWriter.endReturn();'
560 def serializeValue(self, type, instance):
561 serializer = self.serializerFactory()
562 serializer.visit(type, instance)
564 def wrapRet(self, function, instance):
565 self.wrapValue(function.type, instance)
567 def unwrapRet(self, function, instance):
568 self.unwrapValue(function.type, instance)
570 def needsWrapping(self, type):
571 visitor = WrapDecider()
573 return visitor.needsWrapping
575 def wrapValue(self, type, instance):
576 if self.needsWrapping(type):
577 visitor = ValueWrapper()
578 visitor.visit(type, instance)
580 def unwrapValue(self, type, instance):
581 if self.needsWrapping(type):
582 visitor = ValueUnwrapper()
583 visitor.visit(type, instance)
585 def traceInterfaces(self, api):
586 interfaces = api.getAllInterfaces()
589 map(self.declareWrapperInterface, interfaces)
590 self.implementIidWrapper(api)
591 map(self.implementWrapperInterface, interfaces)
594 def declareWrapperInterface(self, interface):
595 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
598 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
599 print " virtual ~%s();" % getWrapperInterfaceName(interface)
601 print " static %s* _Create(const char *functionName, %s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
603 for method in interface.iterMethods():
604 print " " + method.prototype() + ";"
607 for type, name, value in self.enumWrapperInterfaceVariables(interface):
608 print ' %s %s;' % (type, name)
610 print r' virtual void _dummy%i(void) const {' % i
611 print r' os::log("error: %s: unexpected virtual method\n");' % interface.name
612 print r' os::abort();'
617 def enumWrapperInterfaceVariables(self, interface):
619 ("DWORD", "m_dwMagic", "0xd8365d6c"),
620 ("%s *" % interface.name, "m_pInstance", "pInstance"),
621 ("void *", "m_pVtbl", "*(void **)pInstance"),
622 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
625 def implementWrapperInterface(self, interface):
626 self.interface = interface
628 # Private constructor
629 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
630 for type, name, value in self.enumWrapperInterfaceVariables(interface):
631 print ' %s = %s;' % (name, value)
636 print '%s *%s::_Create(const char *functionName, %s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
637 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pInstance);'
638 print r' if (it != g_WrappedObjects.end()) {'
639 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (interface.name, interface.name)
640 print r' assert(pWrapper);'
641 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
642 print r' assert(pWrapper->m_pInstance == pInstance);'
643 print r' if (pWrapper->m_pVtbl == *(void **)pInstance &&'
644 print r' pWrapper->m_NumMethods >= %s) {' % len(list(interface.iterBaseMethods()))
645 #print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);'
646 print r' return pWrapper;'
649 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (interface.name, interface.name)
650 #print r' os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);' % interface.name
651 print r' g_WrappedObjects[pInstance] = pWrapper;'
652 print r' return pWrapper;'
657 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
658 #print r' os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", m_pInstance, this, m_pVtbl);' % interface.name
659 print r' g_WrappedObjects.erase(m_pInstance);'
663 for base, method in interface.iterBaseMethods():
665 self.implementWrapperInterfaceMethod(interface, base, method)
669 def implementWrapperInterfaceMethod(self, interface, base, method):
670 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
673 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (getWrapperInterfaceName(interface) + '::' + method.name)
675 if method.type is not stdapi.Void:
676 print ' %s _result;' % method.type
678 self.implementWrapperInterfaceMethodBody(interface, base, method)
680 if method.type is not stdapi.Void:
681 print ' return _result;'
685 def implementWrapperInterfaceMethodBody(self, interface, base, method):
686 assert not method.internal
688 print ' static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
689 print ' static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (self.getFunctionSigId(), interface.name + '::' + method.name, len(method.args) + 1)
691 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
693 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
694 print ' trace::localWriter.beginArg(0);'
695 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
696 print ' trace::localWriter.endArg();'
697 for arg in method.args:
699 self.unwrapArg(method, arg)
700 self.serializeArg(method, arg)
701 print ' trace::localWriter.endEnter();'
703 self.invokeMethod(interface, base, method)
705 print ' trace::localWriter.beginLeave(_call);'
707 print ' if (%s) {' % self.wasFunctionSuccessful(method)
708 for arg in method.args:
710 self.serializeArg(method, arg)
711 self.wrapArg(method, arg)
714 if method.type is not stdapi.Void:
715 self.serializeRet(method, '_result')
716 if method.type is not stdapi.Void:
717 self.wrapRet(method, '_result')
719 if method.name == 'Release':
720 assert method.type is not stdapi.Void
721 print r' if (!_result) {'
722 print r' delete this;'
725 print ' trace::localWriter.endLeave();'
727 def implementIidWrapper(self, api):
729 print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
730 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",'
731 print r' functionName, reason,'
732 print r' riid.Data1, riid.Data2, riid.Data3,'
733 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]);'
737 print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
738 print r' if (!ppvObj || !*ppvObj) {'
742 for iface in api.getAllInterfaces():
743 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
744 print r' *ppvObj = Wrap%s::_Create(functionName, (%s *) *ppvObj);' % (iface.name, iface.name)
747 print r' %s{' % else_
748 print r' warnIID(functionName, riid, "unknown");'
753 def wrapIid(self, function, riid, out):
754 # Cast output arg to `void **` if necessary
756 obj_type = out.type.type.type
757 if not obj_type is stdapi.Void:
758 assert isinstance(obj_type, stdapi.Interface)
759 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
761 print r' if (%s && *%s) {' % (out.name, out.name)
762 functionName = function.name
764 if self.interface is not None:
765 functionName = self.interface.name + '::' + functionName
766 print r' if (*%s == m_pInstance &&' % (out_name,)
767 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
768 print r' *%s = this;' % (out_name,)
771 print r' %s{' % else_
772 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
776 def invokeMethod(self, interface, base, method):
777 if method.type is stdapi.Void:
780 result = '_result = '
781 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
783 def emit_memcpy(self, dest, src, length):
784 print ' unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
785 print ' trace::localWriter.beginArg(0);'
786 print ' trace::localWriter.writePointer((uintptr_t)%s);' % dest
787 print ' trace::localWriter.endArg();'
788 print ' trace::localWriter.beginArg(1);'
789 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
790 print ' trace::localWriter.endArg();'
791 print ' trace::localWriter.beginArg(2);'
792 print ' trace::localWriter.writeUInt(%s);' % length
793 print ' trace::localWriter.endArg();'
794 print ' trace::localWriter.endEnter();'
795 print ' trace::localWriter.beginLeave(_call);'
796 print ' trace::localWriter.endLeave();'
798 def fake_call(self, function, args):
799 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
800 for arg, instance in zip(function.args, args):
801 assert not arg.output
802 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
803 self.serializeValue(arg.type, instance)
804 print ' trace::localWriter.endArg();'
805 print ' trace::localWriter.endEnter();'
806 print ' trace::localWriter.beginLeave(_fake_call);'
807 print ' trace::localWriter.endLeave();'