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.'''
388 def serializerFactory(self):
389 '''Create a serializer.
391 Can be overriden by derived classes to inject their own serialzer.
394 return ValueSerializer()
396 def traceApi(self, api):
402 for module in api.modules:
403 for header in module.headers:
407 # Generate the serializer functions
408 types = api.getAllTypes()
409 visitor = ComplexValueSerializer(self.serializerFactory())
410 map(visitor.visit, types)
414 self.traceInterfaces(api)
417 self.interface = None
419 for function in api.getAllFunctions():
420 self.traceFunctionDecl(function)
421 for function in api.getAllFunctions():
422 self.traceFunctionImpl(function)
427 def header(self, api):
428 print '#ifdef _WIN32'
429 print '# include <malloc.h> // alloca'
430 print '# ifndef alloca'
431 print '# define alloca _alloca'
434 print '# include <alloca.h> // alloca'
437 print '#include "trace.hpp"'
439 print 'static std::map<void *, void *> g_WrappedObjects;'
441 def footer(self, api):
444 def traceFunctionDecl(self, function):
445 # Per-function declarations
447 if not function.internal:
449 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
451 print 'static const char ** _%s_args = NULL;' % (function.name,)
452 print 'static const trace::FunctionSig _%s_sig = {%u, "%s", %u, _%s_args};' % (function.name, function.id, function.name, len(function.args), function.name)
455 def isFunctionPublic(self, function):
458 def traceFunctionImpl(self, function):
459 if self.isFunctionPublic(function):
460 print 'extern "C" PUBLIC'
462 print 'extern "C" PRIVATE'
463 print function.prototype() + ' {'
464 if function.type is not stdapi.Void:
465 print ' %s _result;' % function.type
467 # No-op if tracing is disabled
468 print ' if (!trace::isTracingEnabled()) {'
469 Tracer.invokeFunction(self, function)
470 if function.type is not stdapi.Void:
471 print ' return _result;'
476 self.traceFunctionImplBody(function)
477 if function.type is not stdapi.Void:
478 print ' return _result;'
482 def traceFunctionImplBody(self, function):
483 if not function.internal:
484 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
485 for arg in function.args:
487 self.unwrapArg(function, arg)
488 self.serializeArg(function, arg)
489 print ' trace::localWriter.endEnter();'
490 self.invokeFunction(function)
491 if not function.internal:
492 print ' trace::localWriter.beginLeave(_call);'
493 print ' if (%s) {' % self.wasFunctionSuccessful(function)
494 for arg in function.args:
496 self.serializeArg(function, arg)
497 self.wrapArg(function, arg)
499 if function.type is not stdapi.Void:
500 self.serializeRet(function, "_result")
501 if function.type is not stdapi.Void:
502 self.wrapRet(function, "_result")
503 print ' trace::localWriter.endLeave();'
505 def invokeFunction(self, function, prefix='_', suffix=''):
506 if function.type is stdapi.Void:
509 result = '_result = '
510 dispatch = prefix + function.name + suffix
511 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
513 def wasFunctionSuccessful(self, function):
514 if function.type is stdapi.Void:
516 if str(function.type) == 'HRESULT':
517 return 'SUCCEEDED(_result)'
520 def serializeArg(self, function, arg):
521 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
522 self.serializeArgValue(function, arg)
523 print ' trace::localWriter.endArg();'
525 def serializeArgValue(self, function, arg):
526 self.serializeValue(arg.type, arg.name)
528 def wrapArg(self, function, arg):
529 assert not isinstance(arg.type, stdapi.ObjPointer)
531 from specs.winapi import REFIID
533 for other_arg in function.args:
534 if not other_arg.output and other_arg.type is REFIID:
536 if riid is not None \
537 and isinstance(arg.type, stdapi.Pointer) \
538 and isinstance(arg.type.type, stdapi.ObjPointer):
539 self.wrapIid(function, riid, arg)
542 self.wrapValue(arg.type, arg.name)
544 def unwrapArg(self, function, arg):
545 self.unwrapValue(arg.type, arg.name)
547 def serializeRet(self, function, instance):
548 print ' trace::localWriter.beginReturn();'
549 self.serializeValue(function.type, instance)
550 print ' trace::localWriter.endReturn();'
552 def serializeValue(self, type, instance):
553 serializer = self.serializerFactory()
554 serializer.visit(type, instance)
556 def wrapRet(self, function, instance):
557 self.wrapValue(function.type, instance)
559 def unwrapRet(self, function, instance):
560 self.unwrapValue(function.type, instance)
562 def needsWrapping(self, type):
563 visitor = WrapDecider()
565 return visitor.needsWrapping
567 def wrapValue(self, type, instance):
568 if self.needsWrapping(type):
569 visitor = ValueWrapper()
570 visitor.visit(type, instance)
572 def unwrapValue(self, type, instance):
573 if self.needsWrapping(type):
574 visitor = ValueUnwrapper()
575 visitor.visit(type, instance)
577 def traceInterfaces(self, api):
578 interfaces = api.getAllInterfaces()
581 map(self.declareWrapperInterface, interfaces)
582 self.implementIidWrapper(api)
583 map(self.implementWrapperInterface, interfaces)
586 def declareWrapperInterface(self, interface):
587 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
590 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
591 print " virtual ~%s();" % getWrapperInterfaceName(interface)
593 print " static %s* _Create(const char *functionName, %s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
595 for method in interface.iterMethods():
596 print " " + method.prototype() + ";"
599 for type, name, value in self.enumWrapperInterfaceVariables(interface):
600 print ' %s %s;' % (type, name)
602 print r' virtual void _dummy%i(void) const {' % i
603 print r' os::log("error: %s: unexpected virtual method\n");' % interface.name
604 print r' os::abort();'
609 def enumWrapperInterfaceVariables(self, interface):
611 ("DWORD", "m_dwMagic", "0xd8365d6c"),
612 ("%s *" % interface.name, "m_pInstance", "pInstance"),
613 ("void *", "m_pVtbl", "*(void **)pInstance"),
614 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
617 def implementWrapperInterface(self, interface):
618 self.interface = interface
620 # Private constructor
621 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
622 for type, name, value in self.enumWrapperInterfaceVariables(interface):
623 print ' %s = %s;' % (name, value)
628 print '%s *%s::_Create(const char *functionName, %s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
629 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pInstance);'
630 print r' if (it != g_WrappedObjects.end()) {'
631 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (interface.name, interface.name)
632 print r' assert(pWrapper);'
633 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
634 print r' assert(pWrapper->m_pInstance == pInstance);'
635 print r' if (pWrapper->m_pVtbl == *(void **)pInstance &&'
636 print r' pWrapper->m_NumMethods >= %s) {' % len(list(interface.iterBaseMethods()))
637 print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);'
638 print r' return pWrapper;'
641 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (interface.name, interface.name)
642 print r' os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);' % interface.name
643 print r' g_WrappedObjects[pInstance] = pWrapper;'
644 print r' return pWrapper;'
649 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
650 print r' os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", m_pInstance, this, m_pVtbl);' % interface.name
651 print r' g_WrappedObjects.erase(m_pInstance);'
655 for base, method in interface.iterBaseMethods():
657 self.implementWrapperInterfaceMethod(interface, base, method)
661 def implementWrapperInterfaceMethod(self, interface, base, method):
662 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
665 print r' os::log("# %s #\n", __FUNCTION__);'
667 if method.type is not stdapi.Void:
668 print ' %s _result;' % method.type
670 self.implementWrapperInterfaceMethodBody(interface, base, method)
672 if method.type is not stdapi.Void:
673 print ' return _result;'
677 def implementWrapperInterfaceMethodBody(self, interface, base, method):
678 assert not method.internal
680 print ' static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
681 print ' static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1)
683 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
685 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
686 print ' trace::localWriter.beginArg(0);'
687 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
688 print ' trace::localWriter.endArg();'
689 for arg in method.args:
691 self.unwrapArg(method, arg)
692 self.serializeArg(method, arg)
693 print ' trace::localWriter.endEnter();'
695 self.invokeMethod(interface, base, method)
697 print ' trace::localWriter.beginLeave(_call);'
699 print ' if (%s) {' % self.wasFunctionSuccessful(method)
700 for arg in method.args:
702 self.serializeArg(method, arg)
703 self.wrapArg(method, arg)
706 if method.type is not stdapi.Void:
707 self.serializeRet(method, '_result')
708 if method.type is not stdapi.Void:
709 self.wrapRet(method, '_result')
711 if method.name == 'Release':
712 assert method.type is not stdapi.Void
713 print r' if (!_result) {'
714 print r' delete this;'
717 print ' trace::localWriter.endLeave();'
719 def implementIidWrapper(self, api):
721 print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
722 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",'
723 print r' functionName, reason,'
724 print r' riid.Data1, riid.Data2, riid.Data3,'
725 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]);'
729 print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
730 print r' if (!ppvObj || !*ppvObj) {'
734 for iface in api.getAllInterfaces():
735 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
736 print r' *ppvObj = Wrap%s::_Create(functionName, (%s *) *ppvObj);' % (iface.name, iface.name)
739 print r' %s{' % else_
740 print r' warnIID(functionName, riid, "unknown");'
745 def wrapIid(self, function, riid, out):
746 # Cast output arg to `void **` if necessary
748 obj_type = out.type.type.type
749 if not obj_type is stdapi.Void:
750 assert isinstance(obj_type, stdapi.Interface)
751 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
753 print r' if (%s && *%s) {' % (out.name, out.name)
754 functionName = function.name
756 if self.interface is not None:
757 functionName = self.interface.name + '::' + functionName
758 print r' if (*%s == m_pInstance &&' % (out_name,)
759 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
760 print r' *%s = this;' % (out_name,)
763 print r' %s{' % else_
764 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
768 def invokeMethod(self, interface, base, method):
769 if method.type is stdapi.Void:
772 result = '_result = '
773 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
775 def emit_memcpy(self, dest, src, length):
776 print ' unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
777 print ' trace::localWriter.beginArg(0);'
778 print ' trace::localWriter.writePointer((uintptr_t)%s);' % dest
779 print ' trace::localWriter.endArg();'
780 print ' trace::localWriter.beginArg(1);'
781 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
782 print ' trace::localWriter.endArg();'
783 print ' trace::localWriter.beginArg(2);'
784 print ' trace::localWriter.writeUInt(%s);' % length
785 print ' trace::localWriter.endArg();'
786 print ' trace::localWriter.endEnter();'
787 print ' trace::localWriter.beginLeave(_call);'
788 print ' trace::localWriter.endLeave();'
790 def fake_call(self, function, args):
791 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
792 for arg, instance in zip(function.args, args):
793 assert not arg.output
794 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
795 self.serializeValue(arg.type, instance)
796 print ' trace::localWriter.endArg();'
797 print ' trace::localWriter.endEnter();'
798 print ' trace::localWriter.beginLeave(_fake_call);'
799 print ' trace::localWriter.endLeave();'