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."""
29 import specs.stdapi as stdapi
32 def getWrapperInterfaceName(interface):
33 return "Wrap" + interface.expr
36 class ComplexValueSerializer(stdapi.OnceVisitor):
37 '''Type visitors which generates serialization functions for
40 Simple types are serialized inline.
43 def __init__(self, serializer):
44 stdapi.OnceVisitor.__init__(self)
45 self.serializer = serializer
47 def visitVoid(self, literal):
50 def visitLiteral(self, literal):
53 def visitString(self, string):
56 def visitConst(self, const):
57 self.visit(const.type)
59 def visitStruct(self, struct):
60 for type, name in struct.members:
62 print 'static void _write__%s(const %s &value) {' % (struct.tag, struct.expr)
63 print ' static const char * members[%u] = {' % (len(struct.members),)
64 for type, name, in struct.members:
65 print ' "%s",' % (name,)
67 print ' static const trace::StructSig sig = {'
68 print ' %u, "%s", %u, members' % (struct.id, struct.name, len(struct.members))
70 print ' trace::localWriter.beginStruct(&sig);'
71 for type, name in struct.members:
72 self.serializer.visit(type, 'value.%s' % (name,))
73 print ' trace::localWriter.endStruct();'
77 def visitArray(self, array):
78 self.visit(array.type)
80 def visitBlob(self, array):
83 def visitEnum(self, enum):
84 print 'static const trace::EnumValue __enum%s_values[] = {' % (enum.tag)
85 for value in enum.values:
86 print ' {"%s", %s},' % (value, value)
89 print 'static const trace::EnumSig __enum%s_sig = {' % (enum.tag)
90 print ' %u, %u, __enum%s_values' % (enum.id, len(enum.values), enum.tag)
94 def visitBitmask(self, bitmask):
95 print 'static const trace::BitmaskFlag __bitmask%s_flags[] = {' % (bitmask.tag)
96 for value in bitmask.values:
97 print ' {"%s", %s},' % (value, value)
100 print 'static const trace::BitmaskSig __bitmask%s_sig = {' % (bitmask.tag)
101 print ' %u, %u, __bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
105 def visitPointer(self, pointer):
106 self.visit(pointer.type)
108 def visitIntPointer(self, pointer):
111 def visitLinearPointer(self, pointer):
112 self.visit(pointer.type)
114 def visitHandle(self, handle):
115 self.visit(handle.type)
117 def visitAlias(self, alias):
118 self.visit(alias.type)
120 def visitOpaque(self, opaque):
123 def visitInterface(self, interface):
126 def visitPolymorphic(self, polymorphic):
127 print 'static void _write__%s(int selector, const %s & value) {' % (polymorphic.tag, polymorphic.expr)
128 print ' switch (selector) {'
129 for cases, type in polymorphic.iterSwitch():
132 self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
139 class ValueSerializer(stdapi.Visitor):
140 '''Visitor which generates code to serialize any type.
142 Simple types are serialized inline here, whereas the serialization of
143 complex types is dispatched to the serialization functions generated by
144 ComplexValueSerializer visitor above.
147 def visitLiteral(self, literal, instance):
148 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
150 def visitString(self, string, instance):
151 if string.kind == 'String':
152 cast = 'const char *'
153 elif string.kind == 'WString':
154 cast = 'const wchar_t *'
157 if cast != string.expr:
158 # reinterpret_cast is necessary for GLubyte * <=> char *
159 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
160 if string.length is not None:
161 length = ', %s' % string.length
164 print ' trace::localWriter.write%s(%s%s);' % (string.kind, instance, length)
166 def visitConst(self, const, instance):
167 self.visit(const.type, instance)
169 def visitStruct(self, struct, instance):
170 print ' _write__%s(%s);' % (struct.tag, instance)
172 def visitArray(self, array, instance):
173 length = '__c' + array.type.tag
174 index = '__i' + array.type.tag
175 print ' if (%s) {' % instance
176 print ' size_t %s = %s;' % (length, array.length)
177 print ' trace::localWriter.beginArray(%s);' % length
178 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
179 print ' trace::localWriter.beginElement();'
180 self.visit(array.type, '(%s)[%s]' % (instance, index))
181 print ' trace::localWriter.endElement();'
183 print ' trace::localWriter.endArray();'
185 print ' trace::localWriter.writeNull();'
188 def visitBlob(self, blob, instance):
189 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size)
191 def visitEnum(self, enum, instance):
192 print ' trace::localWriter.writeEnum(&__enum%s_sig, %s);' % (enum.tag, instance)
194 def visitBitmask(self, bitmask, instance):
195 print ' trace::localWriter.writeBitmask(&__bitmask%s_sig, %s);' % (bitmask.tag, instance)
197 def visitPointer(self, pointer, instance):
198 print ' if (%s) {' % instance
199 print ' trace::localWriter.beginArray(1);'
200 print ' trace::localWriter.beginElement();'
201 self.visit(pointer.type, "*" + instance)
202 print ' trace::localWriter.endElement();'
203 print ' trace::localWriter.endArray();'
205 print ' trace::localWriter.writeNull();'
208 def visitIntPointer(self, pointer, instance):
209 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
211 def visitLinearPointer(self, pointer, instance):
212 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
214 def visitHandle(self, handle, instance):
215 self.visit(handle.type, instance)
217 def visitAlias(self, alias, instance):
218 self.visit(alias.type, instance)
220 def visitOpaque(self, opaque, instance):
221 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
223 def visitInterface(self, interface, instance):
224 print ' trace::localWriter.writeOpaque((const void *)&%s);' % instance
226 def visitPolymorphic(self, polymorphic, instance):
227 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
230 class ValueWrapper(stdapi.Visitor):
231 '''Type visitor which will generate the code to wrap an instance.
233 Wrapping is necessary mostly for interfaces, however interface pointers can
234 appear anywhere inside complex types.
237 def visitVoid(self, type, instance):
238 raise NotImplementedError
240 def visitLiteral(self, type, instance):
243 def visitString(self, type, instance):
246 def visitConst(self, type, instance):
249 def visitStruct(self, struct, instance):
250 for type, name in struct.members:
251 self.visit(type, "(%s).%s" % (instance, name))
253 def visitArray(self, array, instance):
254 # XXX: actually it is possible to return an array of pointers
257 def visitBlob(self, blob, instance):
260 def visitEnum(self, enum, instance):
263 def visitBitmask(self, bitmask, instance):
266 def visitPointer(self, pointer, instance):
267 print " if (%s) {" % instance
268 self.visit(pointer.type, "*" + instance)
271 def visitIntPointer(self, pointer, instance):
274 def visitLinearPointer(self, pointer, instance):
277 def visitHandle(self, handle, instance):
278 self.visit(handle.type, instance)
280 def visitAlias(self, alias, instance):
281 self.visit(alias.type, instance)
283 def visitOpaque(self, opaque, instance):
286 def visitInterface(self, interface, instance):
287 assert instance.startswith('*')
288 instance = instance[1:]
289 print " if (%s) {" % instance
290 print " %s = new %s(%s);" % (instance, getWrapperInterfaceName(interface), instance)
293 def visitPolymorphic(self, type, instance):
294 # XXX: There might be polymorphic values that need wrapping in the future
298 class ValueUnwrapper(ValueWrapper):
299 '''Reverse of ValueWrapper.'''
301 def visitInterface(self, interface, instance):
302 assert instance.startswith('*')
303 instance = instance[1:]
304 print r' if (%s) {' % instance
305 print r' %s *pWrapper = static_cast<%s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
306 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
307 print r' %s = pWrapper->m_pInstance;' % (instance,)
309 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
315 '''Base class to orchestrate the code generation of API tracing.'''
320 def serializerFactory(self):
321 '''Create a serializer.
323 Can be overriden by derived classes to inject their own serialzer.
326 return ValueSerializer()
328 def trace_api(self, api):
334 for header in api.headers:
338 # Generate the serializer functions
339 types = api.getAllTypes()
340 visitor = ComplexValueSerializer(self.serializerFactory())
341 map(visitor.visit, types)
345 interfaces = api.getAllInterfaces()
346 map(self.declareWrapperInterface, interfaces)
347 map(self.implementWrapperInterface, interfaces)
351 map(self.traceFunctionDecl, api.functions)
352 map(self.traceFunctionImpl, api.functions)
357 def header(self, api):
360 def footer(self, api):
363 def traceFunctionDecl(self, function):
364 # Per-function declarations
367 print 'static const char * __%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
369 print 'static const char ** __%s_args = NULL;' % (function.name,)
370 print 'static const trace::FunctionSig __%s_sig = {%u, "%s", %u, __%s_args};' % (function.name, function.id, function.name, len(function.args), function.name)
373 def isFunctionPublic(self, function):
376 def traceFunctionImpl(self, function):
377 if self.isFunctionPublic(function):
378 print 'extern "C" PUBLIC'
380 print 'extern "C" PRIVATE'
381 print function.prototype() + ' {'
382 if function.type is not stdapi.Void:
383 print ' %s __result;' % function.type
384 self.traceFunctionImplBody(function)
385 if function.type is not stdapi.Void:
386 self.wrapRet(function, "__result")
387 print ' return __result;'
391 def traceFunctionImplBody(self, function):
392 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
393 for arg in function.args:
395 self.unwrapArg(function, arg)
396 self.serializeArg(function, arg)
397 print ' trace::localWriter.endEnter();'
398 self.invokeFunction(function)
399 print ' trace::localWriter.beginLeave(__call);'
400 for arg in function.args:
402 self.serializeArg(function, arg)
403 self.wrapArg(function, arg)
404 if function.type is not stdapi.Void:
405 self.serializeRet(function, "__result")
406 print ' trace::localWriter.endLeave();'
408 def invokeFunction(self, function, prefix='__', suffix=''):
409 if function.type is stdapi.Void:
412 result = '__result = '
413 dispatch = prefix + function.name + suffix
414 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
416 def serializeArg(self, function, arg):
417 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
418 self.serializeArgValue(function, arg)
419 print ' trace::localWriter.endArg();'
421 def serializeArgValue(self, function, arg):
422 self.serializeValue(arg.type, arg.name)
424 def wrapArg(self, function, arg):
425 self.wrapValue(arg.type, arg.name)
427 def unwrapArg(self, function, arg):
428 self.unwrapValue(arg.type, arg.name)
430 def serializeRet(self, function, instance):
431 print ' trace::localWriter.beginReturn();'
432 self.serializeValue(function.type, instance)
433 print ' trace::localWriter.endReturn();'
435 def serializeValue(self, type, instance):
436 serializer = self.serializerFactory()
437 serializer.visit(type, instance)
439 def wrapRet(self, function, instance):
440 self.wrapValue(function.type, instance)
442 def unwrapRet(self, function, instance):
443 self.unwrapValue(function.type, instance)
445 def wrapValue(self, type, instance):
446 visitor = ValueWrapper()
447 visitor.visit(type, instance)
449 def unwrapValue(self, type, instance):
450 visitor = ValueUnwrapper()
451 visitor.visit(type, instance)
453 def declareWrapperInterface(self, interface):
454 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
457 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
458 print " virtual ~%s();" % getWrapperInterfaceName(interface)
460 for method in interface.iterMethods():
461 print " " + method.prototype() + ";"
463 self.declareWrapperInterfaceVariables(interface)
467 def declareWrapperInterfaceVariables(self, interface):
469 print " DWORD m_dwMagic;"
470 print " %s * m_pInstance;" % (interface.name,)
472 def implementWrapperInterface(self, interface):
473 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
474 print ' m_dwMagic = 0xd8365d6c;'
475 print ' m_pInstance = pInstance;'
478 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
481 for base, method in interface.iterBaseMethods():
482 self.implementWrapperInterfaceMethod(interface, base, method)
485 def implementWrapperInterfaceMethod(self, interface, base, method):
486 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
487 if method.type is not stdapi.Void:
488 print ' %s __result;' % method.type
490 self.implementWrapperInterfaceMethodBody(interface, base, method)
492 if method.type is not stdapi.Void:
493 print ' return __result;'
497 def implementWrapperInterfaceMethodBody(self, interface, base, method):
498 print ' static const char * __args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
499 print ' static const trace::FunctionSig __sig = {%u, "%s", %u, __args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1)
500 print ' unsigned __call = trace::localWriter.beginEnter(&__sig);'
501 print ' trace::localWriter.beginArg(0);'
502 print ' trace::localWriter.writeOpaque((const void *)m_pInstance);'
503 print ' trace::localWriter.endArg();'
505 from specs.winapi import REFIID
506 from specs.stdapi import Pointer, Opaque, Interface
509 for arg in method.args:
511 self.unwrapArg(method, arg)
512 self.serializeArg(method, arg)
513 if arg.type is REFIID:
515 print ' trace::localWriter.endEnter();'
517 self.invokeMethod(interface, base, method)
519 print ' trace::localWriter.beginLeave(__call);'
520 for arg in method.args:
522 self.serializeArg(method, arg)
523 self.wrapArg(method, arg)
524 if riid is not None and isinstance(arg.type, Pointer):
525 if isinstance(arg.type.type, Opaque):
526 self.wrapIid(riid, arg)
528 assert isinstance(arg.type.type, Pointer)
529 assert isinstance(arg.type.type.type, Interface)
531 if method.type is not stdapi.Void:
532 print ' trace::localWriter.beginReturn();'
533 self.serializeValue(method.type, "__result")
534 print ' trace::localWriter.endReturn();'
535 self.wrapValue(method.type, '__result')
536 print ' trace::localWriter.endLeave();'
537 if method.name == 'Release':
538 assert method.type is not stdapi.Void
539 print ' if (!__result)'
540 print ' delete this;'
542 def wrapIid(self, riid, out):
543 print ' if (%s && *%s) {' % (out.name, out.name)
544 print ' if (*%s == m_pInstance) {' % (out.name,)
545 print ' *%s = this;' % (out.name,)
547 for iface in self.api.getAllInterfaces():
548 print r' else if (%s == IID_%s) {' % (riid.name, iface.name)
549 print r' *%s = new Wrap%s((%s *) *%s);' % (out.name, iface.name, iface.name, out.name)
552 print r' os::log("apitrace: warning: %s: unknown REFIID {0x%08lX,0x%04X,0x%04X,{0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X}}\n",'
553 print r' __FUNCTION__,'
554 print r' %s.Data1, %s.Data2, %s.Data3,' % (riid.name, riid.name, riid.name)
555 print r' %s.Data4[0],' % (riid.name,)
556 print r' %s.Data4[1],' % (riid.name,)
557 print r' %s.Data4[2],' % (riid.name,)
558 print r' %s.Data4[3],' % (riid.name,)
559 print r' %s.Data4[4],' % (riid.name,)
560 print r' %s.Data4[5],' % (riid.name,)
561 print r' %s.Data4[6],' % (riid.name,)
562 print r' %s.Data4[7]);' % (riid.name,)
566 def invokeMethod(self, interface, base, method):
567 if method.type is stdapi.Void:
570 result = '__result = '
571 print ' %sstatic_cast<%s *>(m_pInstance)->%s(%s);' % (result, base, method.name, ', '.join([str(arg.name) for arg in method.args]))
573 def emit_memcpy(self, dest, src, length):
574 print ' unsigned __call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
575 print ' trace::localWriter.beginArg(0);'
576 print ' trace::localWriter.writeOpaque(%s);' % dest
577 print ' trace::localWriter.endArg();'
578 print ' trace::localWriter.beginArg(1);'
579 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
580 print ' trace::localWriter.endArg();'
581 print ' trace::localWriter.beginArg(2);'
582 print ' trace::localWriter.writeUInt(%s);' % length
583 print ' trace::localWriter.endArg();'
584 print ' trace::localWriter.endEnter();'
585 print ' trace::localWriter.beginLeave(__call);'
586 print ' trace::localWriter.endLeave();'