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 visitAttribArray(self, array):
89 def visitBlob(self, array):
92 def visitEnum(self, enum):
93 print 'static const trace::EnumValue _enum%s_values[] = {' % (enum.tag)
94 for value in enum.values:
95 print ' {"%s", %s},' % (value, value)
98 print 'static const trace::EnumSig _enum%s_sig = {' % (enum.tag)
99 print ' %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag)
103 def visitBitmask(self, bitmask):
104 print 'static const trace::BitmaskFlag _bitmask%s_flags[] = {' % (bitmask.tag)
105 for value in bitmask.values:
106 print ' {"%s", %s},' % (value, value)
109 print 'static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag)
110 print ' %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
114 def visitPointer(self, pointer):
115 self.visit(pointer.type)
117 def visitIntPointer(self, pointer):
120 def visitObjPointer(self, pointer):
121 self.visit(pointer.type)
123 def visitLinearPointer(self, pointer):
124 self.visit(pointer.type)
126 def visitHandle(self, handle):
127 self.visit(handle.type)
129 def visitReference(self, reference):
130 self.visit(reference.type)
132 def visitAlias(self, alias):
133 self.visit(alias.type)
135 def visitOpaque(self, opaque):
138 def visitInterface(self, interface):
141 def visitPolymorphic(self, polymorphic):
142 if not polymorphic.contextLess:
144 print 'static void _write__%s(int selector, %s const & value) {' % (polymorphic.tag, polymorphic.expr)
145 print ' switch (selector) {'
146 for cases, type in polymorphic.iterSwitch():
149 self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
156 class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
157 '''Visitor which generates code to serialize any type.
159 Simple types are serialized inline here, whereas the serialization of
160 complex types is dispatched to the serialization functions generated by
161 ComplexValueSerializer visitor above.
164 def visitLiteral(self, literal, instance):
165 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
167 def visitString(self, string, instance):
169 cast = 'const char *'
172 cast = 'const wchar_t *'
174 if cast != string.expr:
175 # reinterpret_cast is necessary for GLubyte * <=> char *
176 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
177 if string.length is not None:
178 length = ', %s' % self.expand(string.length)
181 print ' trace::localWriter.write%s(%s%s);' % (suffix, instance, length)
183 def visitConst(self, const, instance):
184 self.visit(const.type, instance)
186 def visitStruct(self, struct, instance):
187 print ' trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,)
188 for member in struct.members:
189 self.visitMember(member, instance)
190 print ' trace::localWriter.endStruct();'
192 def visitArray(self, array, instance):
193 length = '_c' + array.type.tag
194 index = '_i' + array.type.tag
195 array_length = self.expand(array.length)
196 print ' if (%s) {' % instance
197 print ' size_t %s = %s > 0 ? %s : 0;' % (length, array_length, array_length)
198 print ' trace::localWriter.beginArray(%s);' % length
199 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
200 print ' trace::localWriter.beginElement();'
201 self.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
202 print ' trace::localWriter.endElement();'
204 print ' trace::localWriter.endArray();'
206 print ' trace::localWriter.writeNull();'
209 def visitAttribArray(self, array, instance):
210 # For each element, decide if it is a key or a value (which depends on the previous key).
211 # If it is a value, store it as the right type - usually int, some bitfield, or some enum.
212 # It is currently assumed that an unknown key means that it is followed by an int value.
214 # determine the array length which must be passed to writeArray() up front
215 count = '_c' + array.keyType.tag
216 print ' int %s;' % count
217 print ' for (%(c)s = 0; %(array)s && %(array)s[%(c)s] != %(terminator)s; %(c)s += 2) {' \
218 % {'c': count, 'array': instance, 'terminator': array.terminator}
219 if array.hasKeysWithoutValues:
220 print ' switch (int(%(array)s[%(c)s])) {' % {'array': instance, 'c': count}
221 for key, valueType in array.valueTypes:
222 if valueType is None:
223 print ' case %s:' % key
224 print ' %s--;' % count # the next value is a key again and checked if it's the terminator
228 print ' %(c)s += %(array)s ? 1 : 0;' % {'c': count, 'array': instance}
229 print ' trace::localWriter.beginArray(%s);' % count
231 # for each key / key-value pair write the key and the value, if the key requires one
233 index = '_i' + array.keyType.tag
234 print ' for (int %(i)s = 0; %(i)s < %(count)s; %(i)s++) {' % {'i': index, 'count': count}
235 print ' trace::localWriter.beginElement();'
236 self.visitEnum(array.keyType, "%(array)s[%(i)s]" % {'array': instance, 'i': index})
237 print ' trace::localWriter.endElement();'
238 print ' if (%(i)s + 1 >= %(count)s) {' % {'i': index, 'count': count}
241 print ' switch (int(%(array)s[%(i)s++])) {' % {'array': instance, 'i': index}
242 # write generic value the usual way
243 for key, valueType in array.valueTypes:
244 if valueType is not None:
245 print ' case %s:' % key
246 print ' trace::localWriter.beginElement();'
247 self.visitElement(index, valueType, '(%(array)s)[%(i)s]' % {'array': instance, 'i': index})
248 print ' trace::localWriter.endElement();'
250 # known key with no value, just decrease the index so we treat the next value as a key
251 if array.hasKeysWithoutValues:
252 for key, valueType in array.valueTypes:
253 if valueType is None:
254 print ' case %s:' % key
255 print ' %s--;' % index
257 # unknown key, write an int value
259 print ' trace::localWriter.beginElement();'
260 print ' os::log("apitrace: warning: %s: unknown key 0x%04X, interpreting value as int\\n", ' + \
261 '__FUNCTION__, int(%(array)s[%(i)s]));' % {'array': instance, 'i': index}
262 print ' trace::localWriter.writeSInt(%(array)s[%(i)s]);' % {'array': instance, 'i': index}
263 print ' trace::localWriter.endElement();'
267 print ' trace::localWriter.endArray();'
270 def visitBlob(self, blob, instance):
271 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
273 def visitEnum(self, enum, instance):
274 print ' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
276 def visitBitmask(self, bitmask, instance):
277 print ' trace::localWriter.writeBitmask(&_bitmask%s_sig, %s);' % (bitmask.tag, instance)
279 def visitPointer(self, pointer, instance):
280 print ' if (%s) {' % instance
281 print ' trace::localWriter.beginArray(1);'
282 print ' trace::localWriter.beginElement();'
283 self.visit(pointer.type, "*" + instance)
284 print ' trace::localWriter.endElement();'
285 print ' trace::localWriter.endArray();'
287 print ' trace::localWriter.writeNull();'
290 def visitIntPointer(self, pointer, instance):
291 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
293 def visitObjPointer(self, pointer, instance):
294 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
296 def visitLinearPointer(self, pointer, instance):
297 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
299 def visitReference(self, reference, instance):
300 self.visit(reference.type, instance)
302 def visitHandle(self, handle, instance):
303 self.visit(handle.type, instance)
305 def visitAlias(self, alias, instance):
306 self.visit(alias.type, instance)
308 def visitOpaque(self, opaque, instance):
309 print ' trace::localWriter.writePointer((uintptr_t)%s);' % instance
311 def visitInterface(self, interface, instance):
314 def visitPolymorphic(self, polymorphic, instance):
315 if polymorphic.contextLess:
316 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
318 switchExpr = self.expand(polymorphic.switchExpr)
319 print ' switch (%s) {' % switchExpr
320 for cases, type in polymorphic.iterSwitch():
323 caseInstance = instance
324 if type.expr is not None:
325 caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
326 self.visit(type, caseInstance)
328 if polymorphic.defaultType is None:
330 print r' os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,)
331 print r' trace::localWriter.writeNull();'
336 class WrapDecider(stdapi.Traverser):
337 '''Type visitor which will decide wheter this type will need wrapping or not.
339 For complex types (arrays, structures), we need to know this before hand.
343 self.needsWrapping = False
345 def visitLinearPointer(self, void):
348 def visitInterface(self, interface):
349 self.needsWrapping = True
352 class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
353 '''Type visitor which will generate the code to wrap an instance.
355 Wrapping is necessary mostly for interfaces, however interface pointers can
356 appear anywhere inside complex types.
359 def visitStruct(self, struct, instance):
360 for member in struct.members:
361 self.visitMember(member, instance)
363 def visitArray(self, array, instance):
364 array_length = self.expand(array.length)
365 print " if (%s) {" % instance
366 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
367 self.visitElement('_i', array.type, instance + "[_i]")
371 def visitPointer(self, pointer, instance):
372 print " if (%s) {" % instance
373 self.visit(pointer.type, "*" + instance)
376 def visitObjPointer(self, pointer, instance):
377 elem_type = pointer.type.mutable()
378 if isinstance(elem_type, stdapi.Interface):
379 self.visitInterfacePointer(elem_type, instance)
380 elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
381 self.visitInterfacePointer(elem_type.type, instance)
383 self.visitPointer(pointer, instance)
385 def visitInterface(self, interface, instance):
386 raise NotImplementedError
388 def visitInterfacePointer(self, interface, instance):
389 print " if (%s) {" % instance
390 print " %s = %s::_Create(__FUNCTION__, %s);" % (instance, getWrapperInterfaceName(interface), instance)
393 def visitPolymorphic(self, type, instance):
394 # XXX: There might be polymorphic values that need wrapping in the future
395 raise NotImplementedError
398 class ValueUnwrapper(ValueWrapper):
399 '''Reverse of ValueWrapper.'''
403 def visitStruct(self, struct, instance):
404 if not self.allocated:
405 # Argument is constant. We need to create a non const
407 print " %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct)
408 print ' *_t = %s;' % (instance,)
409 assert instance.startswith('*')
410 print ' %s = _t;' % (instance[1:],)
412 self.allocated = True
414 return ValueWrapper.visitStruct(self, struct, instance)
418 return ValueWrapper.visitStruct(self, struct, instance)
420 def visitArray(self, array, instance):
421 if self.allocated or isinstance(instance, stdapi.Interface):
422 return ValueWrapper.visitArray(self, array, instance)
423 array_length = self.expand(array.length)
424 elem_type = array.type.mutable()
425 print " if (%s && %s) {" % (instance, array_length)
426 print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array_length)
427 print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
428 print " _t[_i] = %s[_i];" % instance
429 self.allocated = True
430 self.visit(array.type, "_t[_i]")
432 print " %s = _t;" % instance
435 def visitInterfacePointer(self, interface, instance):
436 print r' if (%s) {' % instance
437 print r' const %s *pWrapper = static_cast<const %s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
438 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
439 print r' %s = pWrapper->m_pInstance;' % (instance,)
441 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
447 '''Base class to orchestrate the code generation of API tracing.'''
449 # 0-3 are reserved to memcpy, malloc, free, and realloc
455 def serializerFactory(self):
456 '''Create a serializer.
458 Can be overriden by derived classes to inject their own serialzer.
461 return ValueSerializer()
463 def traceApi(self, api):
469 for module in api.modules:
470 for header in module.headers:
474 # Generate the serializer functions
475 types = api.getAllTypes()
476 visitor = ComplexValueSerializer(self.serializerFactory())
477 map(visitor.visit, types)
481 self.traceInterfaces(api)
484 self.interface = None
486 for function in api.getAllFunctions():
487 self.traceFunctionDecl(function)
488 for function in api.getAllFunctions():
489 self.traceFunctionImpl(function)
494 def header(self, api):
495 print '#ifdef _WIN32'
496 print '# include <malloc.h> // alloca'
497 print '# ifndef alloca'
498 print '# define alloca _alloca'
501 print '# include <alloca.h> // alloca'
504 print '#include "trace.hpp"'
506 print 'static std::map<void *, void *> g_WrappedObjects;'
508 def footer(self, api):
511 def traceFunctionDecl(self, function):
512 # Per-function declarations
514 if not function.internal:
516 print 'static const char * _%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
518 print 'static const char ** _%s_args = NULL;' % (function.name,)
519 print 'static const trace::FunctionSig _%s_sig = {%u, "%s", %u, _%s_args};' % (function.name, self.getFunctionSigId(), function.name, len(function.args), function.name)
522 def getFunctionSigId(self):
527 def isFunctionPublic(self, function):
530 def traceFunctionImpl(self, function):
531 if self.isFunctionPublic(function):
532 print 'extern "C" PUBLIC'
534 print 'extern "C" PRIVATE'
535 print function.prototype() + ' {'
536 if function.type is not stdapi.Void:
537 print ' %s _result;' % function.type
539 # No-op if tracing is disabled
540 print ' if (!trace::isTracingEnabled()) {'
541 self.doInvokeFunction(function)
542 if function.type is not stdapi.Void:
543 print ' return _result;'
548 self.traceFunctionImplBody(function)
549 if function.type is not stdapi.Void:
550 print ' return _result;'
554 def traceFunctionImplBody(self, function):
555 if not function.internal:
556 print ' unsigned _call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
557 for arg in function.args:
559 self.unwrapArg(function, arg)
560 for arg in function.args:
562 self.serializeArg(function, arg)
563 print ' trace::localWriter.endEnter();'
564 self.invokeFunction(function)
565 if not function.internal:
566 print ' trace::localWriter.beginLeave(_call);'
567 print ' if (%s) {' % self.wasFunctionSuccessful(function)
568 for arg in function.args:
570 self.serializeArg(function, arg)
571 self.wrapArg(function, arg)
573 if function.type is not stdapi.Void:
574 self.serializeRet(function, "_result")
575 if function.type is not stdapi.Void:
576 self.wrapRet(function, "_result")
577 print ' trace::localWriter.endLeave();'
579 def invokeFunction(self, function):
580 self.doInvokeFunction(function)
582 def doInvokeFunction(self, function, prefix='_', suffix=''):
583 # Same as invokeFunction() but called both when trace is enabled or disabled.
584 if function.type is stdapi.Void:
587 result = '_result = '
588 dispatch = prefix + function.name + suffix
589 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
591 def wasFunctionSuccessful(self, function):
592 if function.type is stdapi.Void:
594 if str(function.type) == 'HRESULT':
595 return 'SUCCEEDED(_result)'
598 def serializeArg(self, function, arg):
599 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
600 self.serializeArgValue(function, arg)
601 print ' trace::localWriter.endArg();'
603 def serializeArgValue(self, function, arg):
604 self.serializeValue(arg.type, arg.name)
606 def wrapArg(self, function, arg):
607 assert not isinstance(arg.type, stdapi.ObjPointer)
609 from specs.winapi import REFIID
611 for other_arg in function.args:
612 if not other_arg.output and other_arg.type is REFIID:
614 if riid is not None \
615 and isinstance(arg.type, stdapi.Pointer) \
616 and isinstance(arg.type.type, stdapi.ObjPointer):
617 self.wrapIid(function, riid, arg)
620 self.wrapValue(arg.type, arg.name)
622 def unwrapArg(self, function, arg):
623 self.unwrapValue(arg.type, arg.name)
625 def serializeRet(self, function, instance):
626 print ' trace::localWriter.beginReturn();'
627 self.serializeValue(function.type, instance)
628 print ' trace::localWriter.endReturn();'
630 def serializeValue(self, type, instance):
631 serializer = self.serializerFactory()
632 serializer.visit(type, instance)
634 def wrapRet(self, function, instance):
635 self.wrapValue(function.type, instance)
637 def needsWrapping(self, type):
638 visitor = WrapDecider()
640 return visitor.needsWrapping
642 def wrapValue(self, type, instance):
643 if self.needsWrapping(type):
644 visitor = ValueWrapper()
645 visitor.visit(type, instance)
647 def unwrapValue(self, type, instance):
648 if self.needsWrapping(type):
649 visitor = ValueUnwrapper()
650 visitor.visit(type, instance)
652 def traceInterfaces(self, api):
653 interfaces = api.getAllInterfaces()
656 map(self.declareWrapperInterface, interfaces)
657 self.implementIidWrapper(api)
658 map(self.implementWrapperInterface, interfaces)
661 def declareWrapperInterface(self, interface):
662 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
665 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
666 print " virtual ~%s();" % getWrapperInterfaceName(interface)
668 print " static %s* _Create(const char *functionName, %s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
670 for method in interface.iterMethods():
671 print " " + method.prototype() + ";"
674 for type, name, value in self.enumWrapperInterfaceVariables(interface):
675 print ' %s %s;' % (type, name)
677 print r' virtual void _dummy%i(void) const {' % i
678 print r' os::log("error: %s: unexpected virtual method\n");' % interface.name
679 print r' os::abort();'
684 def enumWrapperInterfaceVariables(self, interface):
686 ("DWORD", "m_dwMagic", "0xd8365d6c"),
687 ("%s *" % interface.name, "m_pInstance", "pInstance"),
688 ("void *", "m_pVtbl", "*(void **)pInstance"),
689 ("UINT", "m_NumMethods", len(list(interface.iterBaseMethods()))),
692 def implementWrapperInterface(self, interface):
693 self.interface = interface
695 # Private constructor
696 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
697 for type, name, value in self.enumWrapperInterfaceVariables(interface):
698 if value is not None:
699 print ' %s = %s;' % (name, value)
704 print '%s *%s::_Create(const char *functionName, %s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
705 print r' std::map<void *, void *>::const_iterator it = g_WrappedObjects.find(pInstance);'
706 print r' if (it != g_WrappedObjects.end()) {'
707 print r' Wrap%s *pWrapper = (Wrap%s *)it->second;' % (interface.name, interface.name)
708 print r' assert(pWrapper);'
709 print r' assert(pWrapper->m_dwMagic == 0xd8365d6c);'
710 print r' assert(pWrapper->m_pInstance == pInstance);'
711 print r' if (pWrapper->m_pVtbl == *(void **)pInstance &&'
712 print r' pWrapper->m_NumMethods >= %s) {' % len(list(interface.iterBaseMethods()))
713 #print r' os::log("%s: fetched pvObj=%p pWrapper=%p pVtbl=%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);'
714 print r' return pWrapper;'
717 print r' Wrap%s *pWrapper = new Wrap%s(pInstance);' % (interface.name, interface.name)
718 #print r' os::log("%%s: created %s pvObj=%%p pWrapper=%%p pVtbl=%%p\n", functionName, pInstance, pWrapper, pWrapper->m_pVtbl);' % interface.name
719 print r' g_WrappedObjects[pInstance] = pWrapper;'
720 print r' return pWrapper;'
725 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
726 #print r' os::log("%s::Release: deleted pvObj=%%p pWrapper=%%p pVtbl=%%p\n", m_pInstance, this, m_pVtbl);' % interface.name
727 print r' g_WrappedObjects.erase(m_pInstance);'
731 for base, method in interface.iterBaseMethods():
733 self.implementWrapperInterfaceMethod(interface, base, method)
737 def implementWrapperInterfaceMethod(self, interface, base, method):
738 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
741 print r' os::log("%%s(%%p -> %%p)\n", "%s", this, m_pInstance);' % (getWrapperInterfaceName(interface) + '::' + method.name)
743 if method.type is not stdapi.Void:
744 print ' %s _result;' % method.type
746 self.implementWrapperInterfaceMethodBody(interface, base, method)
748 if method.type is not stdapi.Void:
749 print ' return _result;'
753 def implementWrapperInterfaceMethodBody(self, interface, base, method):
754 assert not method.internal
756 print ' static const char * _args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
757 print ' static const trace::FunctionSig _sig = {%u, "%s", %u, _args};' % (self.getFunctionSigId(), interface.name + '::' + method.name, len(method.args) + 1)
759 print ' %s *_this = static_cast<%s *>(m_pInstance);' % (base, base)
761 print ' unsigned _call = trace::localWriter.beginEnter(&_sig);'
762 print ' trace::localWriter.beginArg(0);'
763 print ' trace::localWriter.writePointer((uintptr_t)m_pInstance);'
764 print ' trace::localWriter.endArg();'
765 for arg in method.args:
767 self.unwrapArg(method, arg)
768 for arg in method.args:
770 self.serializeArg(method, arg)
771 print ' trace::localWriter.endEnter();'
773 self.invokeMethod(interface, base, method)
775 print ' trace::localWriter.beginLeave(_call);'
777 print ' if (%s) {' % self.wasFunctionSuccessful(method)
778 for arg in method.args:
780 self.serializeArg(method, arg)
781 self.wrapArg(method, arg)
784 if method.type is not stdapi.Void:
785 self.serializeRet(method, '_result')
786 if method.type is not stdapi.Void:
787 self.wrapRet(method, '_result')
789 if method.name == 'Release':
790 assert method.type is not stdapi.Void
791 print r' if (!_result) {'
792 print r' delete this;'
795 print ' trace::localWriter.endLeave();'
797 def implementIidWrapper(self, api):
799 print r'warnIID(const char *functionName, REFIID riid, const char *reason) {'
800 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",'
801 print r' functionName, reason,'
802 print r' riid.Data1, riid.Data2, riid.Data3,'
803 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]);'
807 print r'wrapIID(const char *functionName, REFIID riid, void * * ppvObj) {'
808 print r' if (!ppvObj || !*ppvObj) {'
812 for iface in api.getAllInterfaces():
813 print r' %sif (riid == IID_%s) {' % (else_, iface.name)
814 print r' *ppvObj = Wrap%s::_Create(functionName, (%s *) *ppvObj);' % (iface.name, iface.name)
817 print r' %s{' % else_
818 print r' warnIID(functionName, riid, "unknown");'
823 def wrapIid(self, function, riid, out):
824 # Cast output arg to `void **` if necessary
826 obj_type = out.type.type.type
827 if not obj_type is stdapi.Void:
828 assert isinstance(obj_type, stdapi.Interface)
829 out_name = 'reinterpret_cast<void * *>(%s)' % out_name
831 print r' if (%s && *%s) {' % (out.name, out.name)
832 functionName = function.name
834 if self.interface is not None:
835 functionName = self.interface.name + '::' + functionName
836 print r' if (*%s == m_pInstance &&' % (out_name,)
837 print r' (%s)) {' % ' || '.join('%s == IID_%s' % (riid.name, iface.name) for iface in self.interface.iterBases())
838 print r' *%s = this;' % (out_name,)
841 print r' %s{' % else_
842 print r' wrapIID("%s", %s, %s);' % (functionName, riid.name, out_name)
846 def invokeMethod(self, interface, base, method):
847 if method.type is stdapi.Void:
850 result = '_result = '
851 print ' %s_this->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
853 def emit_memcpy(self, dest, src, length):
854 print ' unsigned _call = trace::localWriter.beginEnter(&trace::memcpy_sig, true);'
855 print ' trace::localWriter.beginArg(0);'
856 print ' trace::localWriter.writePointer((uintptr_t)%s);' % dest
857 print ' trace::localWriter.endArg();'
858 print ' trace::localWriter.beginArg(1);'
859 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
860 print ' trace::localWriter.endArg();'
861 print ' trace::localWriter.beginArg(2);'
862 print ' trace::localWriter.writeUInt(%s);' % length
863 print ' trace::localWriter.endArg();'
864 print ' trace::localWriter.endEnter();'
865 print ' trace::localWriter.beginLeave(_call);'
866 print ' trace::localWriter.endLeave();'
868 def fake_call(self, function, args):
869 print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
870 for arg, instance in zip(function.args, args):
871 assert not arg.output
872 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
873 self.serializeValue(arg.type, instance)
874 print ' trace::localWriter.endArg();'
875 print ' trace::localWriter.endEnter();'
876 print ' trace::localWriter.beginLeave(_fake_call);'
877 print ' trace::localWriter.endLeave();'