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 function.name == 'glXCreatePixmap':
492 print ' emit_fake_x_create_pixmap(dpy, pixmap);'
493 if function.name == 'glXBindTexImageEXT':
494 print ' emit_fake_put_image_data(display, underlying_x_pixmaps[drawable]);'
495 if not function.internal:
496 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
497 for arg in function.args:
499 self.unwrapArg(function, arg)
500 for arg in function.args:
502 self.serializeArg(function, arg)
503 print ' trace::localWriter.endEnter();'
504 self.invokeFunction(function)
505 if function.name == 'glXCreatePixmap':
506 print ' underlying_x_pixmaps[_result] = pixmap;'
507 if not function.internal:
508 print ' trace::localWriter.beginLeave(_call);'
509 print ' if (%s) {' % self.wasFunctionSuccessful(function)
510 for arg in function.args:
512 self.serializeArg(function, arg)
513 self.wrapArg(function, arg)
515 if function.type is not stdapi.Void:
516 self.serializeRet(function, "_result")
517 if function.type is not stdapi.Void:
518 self.wrapRet(function, "_result")
519 print ' trace::localWriter.endLeave();'
521 def invokeFunction(self, function, prefix='_', suffix=''):
522 if function.type is stdapi.Void:
525 result = '_result = '
526 dispatch = prefix + function.name + suffix
527 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
529 def wasFunctionSuccessful(self, function):
530 if function.type is stdapi.Void:
532 if str(function.type) == 'HRESULT':
533 return 'SUCCEEDED(_result)'
536 def serializeArg(self, function, arg):
537 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
538 self.serializeArgValue(function, arg)
539 print ' trace::localWriter.endArg();'
541 def serializeArgValue(self, function, arg):
542 self.serializeValue(arg.type, arg.name)
544 def wrapArg(self, function, arg):
545 assert not isinstance(arg.type, stdapi.ObjPointer)
547 from specs.winapi import REFIID
549 for other_arg in function.args:
550 if not other_arg.output and other_arg.type is REFIID:
552 if riid is not None \
553 and isinstance(arg.type, stdapi.Pointer) \
554 and isinstance(arg.type.type, stdapi.ObjPointer):
555 self.wrapIid(function, riid, arg)
558 self.wrapValue(arg.type, arg.name)
560 def unwrapArg(self, function, arg):
561 self.unwrapValue(arg.type, arg.name)
563 def serializeRet(self, function, instance):
564 print ' trace::localWriter.beginReturn();'
565 self.serializeValue(function.type, instance)
566 print ' trace::localWriter.endReturn();'
568 def serializeValue(self, type, instance):
569 serializer = self.serializerFactory()
570 serializer.visit(type, instance)
572 def wrapRet(self, function, instance):
573 self.wrapValue(function.type, instance)
575 def needsWrapping(self, type):
576 visitor = WrapDecider()
578 return visitor.needsWrapping
580 def wrapValue(self, type, instance):
581 if self.needsWrapping(type):
582 visitor = ValueWrapper()
583 visitor.visit(type, instance)
585 def unwrapValue(self, type, instance):
586 if self.needsWrapping(type):
587 visitor = ValueUnwrapper()
588 visitor.visit(type, instance)
590 def traceInterfaces(self, api):
591 interfaces = api.getAllInterfaces()
594 map(self.declareWrapperInterface, interfaces)
595 self.implementIidWrapper(api)
596 map(self.implementWrapperInterface, interfaces)
599 def declareWrapperInterface(self, interface):
600 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
603 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
604 print " virtual ~%s();" % getWrapperInterfaceName(interface)
606 print " static %s* _Create(const char *functionName, %s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
608 for method in interface.iterMethods():
609 print " " + method.prototype() + ";"
612 for type, name, value in self.enumWrapperInterfaceVariables(interface):
613 print ' %s %s;' % (type, name)
615 print r' virtual void _dummy%i(void) const {' % i
616 print r' os::log("error: %s: unexpected virtual method\n");' % interface.name
617 print r' os::abort();'
622 def enumWrapperInterfaceVariables(self, interface):
624 ("DWORD", "m_dwMagic", "0xd8365d6c"),
625 ("%s *" % interface.name, "m_pInstance", "pInstance"),
626 ("void *", "m_pVtbl", "*(void **)pInstance"),
627 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
630 def implementWrapperInterface(self, interface):
631 self.interface = interface
633 # Private constructor
634 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
635 for type, name, value in self.enumWrapperInterfaceVariables(interface):
636 print ' %s = %s;' % (name, value)
641 print '%s *%s::_Create(const char *functionName, %s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
642 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pInstance);'
643 print r' if (it != g_WrappedObjects.end()) {'
644 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (interface.name, interface.name)
645 print r' assert(pWrapper);'
646 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
647 print r' assert(pWrapper->m_pInstance == pInstance);'
648 print r' if (pWrapper->m_pVtbl == *(void **)pInstance &&'
649 print r' pWrapper->m_NumMethods >= %s) {' % len(list(interface.iterBaseMethods()))
650 #print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);'
651 print r' return pWrapper;'
654 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (interface.name, interface.name)
655 #print r' os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);' % interface.name
656 print r' g_WrappedObjects[pInstance] = pWrapper;'
657 print r' return pWrapper;'
662 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
663 #print r' os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", m_pInstance, this, m_pVtbl);' % interface.name
664 print r' g_WrappedObjects.erase(m_pInstance);'
668 for base, method in interface.iterBaseMethods():
670 self.implementWrapperInterfaceMethod(interface, base, method)
674 def implementWrapperInterfaceMethod(self, interface, base, method):
675 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
678 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (getWrapperInterfaceName(interface) + '::' + method.name)
680 if method.type is not stdapi.Void:
681 print ' %s _result;' % method.type
683 self.implementWrapperInterfaceMethodBody(interface, base, method)
685 if method.type is not stdapi.Void:
686 print ' return _result;'
690 def implementWrapperInterfaceMethodBody(self, interface, base, method):
691 assert not method.internal
693 print ' static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
694 print ' static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (self.getFunctionSigId(), interface.name + '::' + method.name, len(method.args) + 1)
696 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
698 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
699 print ' trace::localWriter.beginArg(0);'
700 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
701 print ' trace::localWriter.endArg();'
702 for arg in method.args:
704 self.unwrapArg(method, arg)
705 for arg in method.args:
707 self.serializeArg(method, arg)
708 print ' trace::localWriter.endEnter();'
710 self.invokeMethod(interface, base, method)
712 print ' trace::localWriter.beginLeave(_call);'
714 print ' if (%s) {' % self.wasFunctionSuccessful(method)
715 for arg in method.args:
717 self.serializeArg(method, arg)
718 self.wrapArg(method, arg)
721 if method.type is not stdapi.Void:
722 self.serializeRet(method, '_result')
723 if method.type is not stdapi.Void:
724 self.wrapRet(method, '_result')
726 if method.name == 'Release':
727 assert method.type is not stdapi.Void
728 print r' if (!_result) {'
729 print r' delete this;'
732 print ' trace::localWriter.endLeave();'
734 def implementIidWrapper(self, api):
736 print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
737 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",'
738 print r' functionName, reason,'
739 print r' riid.Data1, riid.Data2, riid.Data3,'
740 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]);'
744 print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
745 print r' if (!ppvObj || !*ppvObj) {'
749 for iface in api.getAllInterfaces():
750 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
751 print r' *ppvObj = Wrap%s::_Create(functionName, (%s *) *ppvObj);' % (iface.name, iface.name)
754 print r' %s{' % else_
755 print r' warnIID(functionName, riid, "unknown");'
760 def wrapIid(self, function, riid, out):
761 # Cast output arg to `void **` if necessary
763 obj_type = out.type.type.type
764 if not obj_type is stdapi.Void:
765 assert isinstance(obj_type, stdapi.Interface)
766 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
768 print r' if (%s && *%s) {' % (out.name, out.name)
769 functionName = function.name
771 if self.interface is not None:
772 functionName = self.interface.name + '::' + functionName
773 print r' if (*%s == m_pInstance &&' % (out_name,)
774 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
775 print r' *%s = this;' % (out_name,)
778 print r' %s{' % else_
779 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
783 def invokeMethod(self, interface, base, method):
784 if method.type is stdapi.Void:
787 result = '_result = '
788 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
790 def emit_memcpy(self, dest, src, length):
791 print ' unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
792 print ' trace::localWriter.beginArg(0);'
793 print ' trace::localWriter.writePointer((uintptr_t)%s);' % dest
794 print ' trace::localWriter.endArg();'
795 print ' trace::localWriter.beginArg(1);'
796 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
797 print ' trace::localWriter.endArg();'
798 print ' trace::localWriter.beginArg(2);'
799 print ' trace::localWriter.writeUInt(%s);' % length
800 print ' trace::localWriter.endArg();'
801 print ' trace::localWriter.endEnter();'
802 print ' trace::localWriter.beginLeave(_call);'
803 print ' trace::localWriter.endLeave();'
805 def fake_call(self, function, args):
806 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
807 for arg, instance in zip(function.args, args):
808 assert not arg.output
809 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
810 self.serializeValue(arg.type, instance)
811 print ' trace::localWriter.endArg();'
812 print ' trace::localWriter.endEnter();'
813 print ' trace::localWriter.beginLeave(_fake_call);'
814 print ' trace::localWriter.endLeave();'