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 visitObjPointer(self, pointer):
112 self.visit(pointer.type)
114 def visitLinearPointer(self, pointer):
115 self.visit(pointer.type)
117 def visitHandle(self, handle):
118 self.visit(handle.type)
120 def visitReference(self, reference):
121 self.visit(reference.type)
123 def visitAlias(self, alias):
124 self.visit(alias.type)
126 def visitOpaque(self, opaque):
129 def visitInterface(self, interface):
132 def visitPolymorphic(self, polymorphic):
133 print 'static void _write__%s(int selector, const %s & value) {' % (polymorphic.tag, polymorphic.expr)
134 print ' switch (selector) {'
135 for cases, type in polymorphic.iterSwitch():
138 self.serializer.visit(type, 'static_cast<%s>(value)' % (type,))
145 class ValueSerializer(stdapi.Visitor):
146 '''Visitor which generates code to serialize any type.
148 Simple types are serialized inline here, whereas the serialization of
149 complex types is dispatched to the serialization functions generated by
150 ComplexValueSerializer visitor above.
153 def visitLiteral(self, literal, instance):
154 print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
156 def visitString(self, string, instance):
157 if string.kind == 'String':
158 cast = 'const char *'
159 elif string.kind == 'WString':
160 cast = 'const wchar_t *'
163 if cast != string.expr:
164 # reinterpret_cast is necessary for GLubyte * <=> char *
165 instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
166 if string.length is not None:
167 length = ', %s' % string.length
170 print ' trace::localWriter.write%s(%s%s);' % (string.kind, instance, length)
172 def visitConst(self, const, instance):
173 self.visit(const.type, instance)
175 def visitStruct(self, struct, instance):
176 print ' _write__%s(%s);' % (struct.tag, instance)
178 def visitArray(self, array, instance):
179 length = '__c' + array.type.tag
180 index = '__i' + array.type.tag
181 print ' if (%s) {' % instance
182 print ' size_t %s = %s;' % (length, array.length)
183 print ' trace::localWriter.beginArray(%s);' % length
184 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
185 print ' trace::localWriter.beginElement();'
186 self.visit(array.type, '(%s)[%s]' % (instance, index))
187 print ' trace::localWriter.endElement();'
189 print ' trace::localWriter.endArray();'
191 print ' trace::localWriter.writeNull();'
194 def visitBlob(self, blob, instance):
195 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size)
197 def visitEnum(self, enum, instance):
198 print ' trace::localWriter.writeEnum(&__enum%s_sig, %s);' % (enum.tag, instance)
200 def visitBitmask(self, bitmask, instance):
201 print ' trace::localWriter.writeBitmask(&__bitmask%s_sig, %s);' % (bitmask.tag, instance)
203 def visitPointer(self, pointer, instance):
204 print ' if (%s) {' % instance
205 print ' trace::localWriter.beginArray(1);'
206 print ' trace::localWriter.beginElement();'
207 self.visit(pointer.type, "*" + instance)
208 print ' trace::localWriter.endElement();'
209 print ' trace::localWriter.endArray();'
211 print ' trace::localWriter.writeNull();'
214 def visitIntPointer(self, pointer, instance):
215 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
217 def visitObjPointer(self, pointer, instance):
218 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
220 def visitLinearPointer(self, pointer, instance):
221 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
223 def visitReference(self, reference, instance):
224 self.visit(reference.type, instance)
226 def visitHandle(self, handle, instance):
227 self.visit(handle.type, instance)
229 def visitAlias(self, alias, instance):
230 self.visit(alias.type, instance)
232 def visitOpaque(self, opaque, instance):
233 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
235 def visitInterface(self, interface, instance):
236 print ' trace::localWriter.writeOpaque((const void *)&%s);' % instance
238 def visitPolymorphic(self, polymorphic, instance):
239 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
242 class ValueWrapper(stdapi.Visitor):
243 '''Type visitor which will generate the code to wrap an instance.
245 Wrapping is necessary mostly for interfaces, however interface pointers can
246 appear anywhere inside complex types.
249 def visitVoid(self, type, instance):
250 raise NotImplementedError
252 def visitLiteral(self, type, instance):
255 def visitString(self, type, instance):
258 def visitConst(self, type, instance):
261 def visitStruct(self, struct, instance):
262 for type, name in struct.members:
263 self.visit(type, "(%s).%s" % (instance, name))
265 def visitArray(self, array, instance):
266 # XXX: actually it is possible to return an array of pointers
269 def visitBlob(self, blob, instance):
272 def visitEnum(self, enum, instance):
275 def visitBitmask(self, bitmask, instance):
278 def visitPointer(self, pointer, instance):
279 print " if (%s) {" % instance
280 self.visit(pointer.type, "*" + instance)
283 def visitIntPointer(self, pointer, instance):
286 def visitObjPointer(self, pointer, instance):
287 print " if (%s) {" % instance
288 self.visit(pointer.type, "*" + instance)
291 def visitLinearPointer(self, pointer, instance):
294 def visitReference(self, reference, instance):
295 self.visit(reference.type, instance)
297 def visitHandle(self, handle, instance):
298 self.visit(handle.type, instance)
300 def visitAlias(self, alias, instance):
301 self.visit(alias.type, instance)
303 def visitOpaque(self, opaque, instance):
306 def visitInterface(self, interface, instance):
307 assert instance.startswith('*')
308 instance = instance[1:]
309 print " if (%s) {" % instance
310 print " %s = new %s(%s);" % (instance, getWrapperInterfaceName(interface), instance)
313 def visitPolymorphic(self, type, instance):
314 # XXX: There might be polymorphic values that need wrapping in the future
318 class ValueUnwrapper(ValueWrapper):
319 '''Reverse of ValueWrapper.'''
321 def visitInterface(self, interface, instance):
322 assert instance.startswith('*')
323 instance = instance[1:]
324 print r' if (%s) {' % instance
325 print r' %s *pWrapper = static_cast<%s*>(%s);' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), instance)
326 print r' if (pWrapper && pWrapper->m_dwMagic == 0xd8365d6c) {'
327 print r' %s = pWrapper->m_pInstance;' % (instance,)
329 print r' os::log("apitrace: warning: %%s: unexpected %%s pointer\n", __FUNCTION__, "%s");' % interface.name
335 '''Base class to orchestrate the code generation of API tracing.'''
340 def serializerFactory(self):
341 '''Create a serializer.
343 Can be overriden by derived classes to inject their own serialzer.
346 return ValueSerializer()
348 def trace_api(self, api):
354 for header in api.headers:
358 # Generate the serializer functions
359 types = api.getAllTypes()
360 visitor = ComplexValueSerializer(self.serializerFactory())
361 map(visitor.visit, types)
365 interfaces = api.getAllInterfaces()
366 map(self.declareWrapperInterface, interfaces)
367 map(self.implementWrapperInterface, interfaces)
371 map(self.traceFunctionDecl, api.functions)
372 map(self.traceFunctionImpl, api.functions)
377 def header(self, api):
380 def footer(self, api):
383 def traceFunctionDecl(self, function):
384 # Per-function declarations
387 print 'static const char * __%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
389 print 'static const char ** __%s_args = NULL;' % (function.name,)
390 print 'static const trace::FunctionSig __%s_sig = {%u, "%s", %u, __%s_args};' % (function.name, function.id, function.name, len(function.args), function.name)
393 def isFunctionPublic(self, function):
396 def traceFunctionImpl(self, function):
397 if self.isFunctionPublic(function):
398 print 'extern "C" PUBLIC'
400 print 'extern "C" PRIVATE'
401 print function.prototype() + ' {'
402 if function.type is not stdapi.Void:
403 print ' %s __result;' % function.type
404 self.traceFunctionImplBody(function)
405 if function.type is not stdapi.Void:
406 self.wrapRet(function, "__result")
407 print ' return __result;'
411 def traceFunctionImplBody(self, function):
412 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
413 for arg in function.args:
415 self.unwrapArg(function, arg)
416 self.serializeArg(function, arg)
417 print ' trace::localWriter.endEnter();'
418 self.invokeFunction(function)
419 print ' trace::localWriter.beginLeave(__call);'
420 for arg in function.args:
422 self.serializeArg(function, arg)
423 self.wrapArg(function, arg)
424 if function.type is not stdapi.Void:
425 self.serializeRet(function, "__result")
426 print ' trace::localWriter.endLeave();'
428 def invokeFunction(self, function, prefix='__', suffix=''):
429 if function.type is stdapi.Void:
432 result = '__result = '
433 dispatch = prefix + function.name + suffix
434 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
436 def serializeArg(self, function, arg):
437 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
438 self.serializeArgValue(function, arg)
439 print ' trace::localWriter.endArg();'
441 def serializeArgValue(self, function, arg):
442 self.serializeValue(arg.type, arg.name)
444 def wrapArg(self, function, arg):
445 self.wrapValue(arg.type, arg.name)
447 def unwrapArg(self, function, arg):
448 self.unwrapValue(arg.type, arg.name)
450 def serializeRet(self, function, instance):
451 print ' trace::localWriter.beginReturn();'
452 self.serializeValue(function.type, instance)
453 print ' trace::localWriter.endReturn();'
455 def serializeValue(self, type, instance):
456 serializer = self.serializerFactory()
457 serializer.visit(type, instance)
459 def wrapRet(self, function, instance):
460 self.wrapValue(function.type, instance)
462 def unwrapRet(self, function, instance):
463 self.unwrapValue(function.type, instance)
465 def wrapValue(self, type, instance):
466 visitor = ValueWrapper()
467 visitor.visit(type, instance)
469 def unwrapValue(self, type, instance):
470 visitor = ValueUnwrapper()
471 visitor.visit(type, instance)
473 def declareWrapperInterface(self, interface):
474 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
477 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
478 print " virtual ~%s();" % getWrapperInterfaceName(interface)
480 for method in interface.iterMethods():
481 print " " + method.prototype() + ";"
483 self.declareWrapperInterfaceVariables(interface)
487 def declareWrapperInterfaceVariables(self, interface):
489 print " DWORD m_dwMagic;"
490 print " %s * m_pInstance;" % (interface.name,)
492 def implementWrapperInterface(self, interface):
493 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
494 print ' m_dwMagic = 0xd8365d6c;'
495 print ' m_pInstance = pInstance;'
498 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
501 for base, method in interface.iterBaseMethods():
502 self.implementWrapperInterfaceMethod(interface, base, method)
505 def implementWrapperInterfaceMethod(self, interface, base, method):
506 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
507 if method.type is not stdapi.Void:
508 print ' %s __result;' % method.type
510 self.implementWrapperInterfaceMethodBody(interface, base, method)
512 if method.type is not stdapi.Void:
513 print ' return __result;'
517 def implementWrapperInterfaceMethodBody(self, interface, base, method):
518 print ' static const char * __args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
519 print ' static const trace::FunctionSig __sig = {%u, "%s", %u, __args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1)
520 print ' unsigned __call = trace::localWriter.beginEnter(&__sig);'
521 print ' trace::localWriter.beginArg(0);'
522 print ' trace::localWriter.writeOpaque((const void *)m_pInstance);'
523 print ' trace::localWriter.endArg();'
525 from specs.winapi import REFIID
526 from specs.stdapi import Pointer, Opaque, Interface
529 for arg in method.args:
531 self.unwrapArg(method, arg)
532 self.serializeArg(method, arg)
533 if arg.type is REFIID:
535 print ' trace::localWriter.endEnter();'
537 self.invokeMethod(interface, base, method)
539 print ' trace::localWriter.beginLeave(__call);'
540 for arg in method.args:
542 self.serializeArg(method, arg)
543 self.wrapArg(method, arg)
544 if riid is not None and isinstance(arg.type, Pointer):
545 if isinstance(arg.type.type, Opaque):
546 self.wrapIid(riid, arg)
548 assert isinstance(arg.type.type, Pointer)
549 assert isinstance(arg.type.type.type, Interface)
551 if method.type is not stdapi.Void:
552 print ' trace::localWriter.beginReturn();'
553 self.serializeValue(method.type, "__result")
554 print ' trace::localWriter.endReturn();'
555 self.wrapValue(method.type, '__result')
556 print ' trace::localWriter.endLeave();'
557 if method.name == 'Release':
558 assert method.type is not stdapi.Void
559 print ' if (!__result)'
560 print ' delete this;'
562 def wrapIid(self, riid, out):
563 print ' if (%s && *%s) {' % (out.name, out.name)
564 print ' if (*%s == m_pInstance) {' % (out.name,)
565 print ' *%s = this;' % (out.name,)
567 for iface in self.api.getAllInterfaces():
568 print r' else if (%s == IID_%s) {' % (riid.name, iface.name)
569 print r' *%s = new Wrap%s((%s *) *%s);' % (out.name, iface.name, iface.name, out.name)
572 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",'
573 print r' __FUNCTION__,'
574 print r' %s.Data1, %s.Data2, %s.Data3,' % (riid.name, riid.name, riid.name)
575 print r' %s.Data4[0],' % (riid.name,)
576 print r' %s.Data4[1],' % (riid.name,)
577 print r' %s.Data4[2],' % (riid.name,)
578 print r' %s.Data4[3],' % (riid.name,)
579 print r' %s.Data4[4],' % (riid.name,)
580 print r' %s.Data4[5],' % (riid.name,)
581 print r' %s.Data4[6],' % (riid.name,)
582 print r' %s.Data4[7]);' % (riid.name,)
586 def invokeMethod(self, interface, base, method):
587 if method.type is stdapi.Void:
590 result = '__result = '
591 print ' %sstatic_cast<%s *>(m_pInstance)->%s(%s);' % (result, base, method.name, ', '.join([str(arg.name) for arg in method.args]))
593 def emit_memcpy(self, dest, src, length):
594 print ' unsigned __call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
595 print ' trace::localWriter.beginArg(0);'
596 print ' trace::localWriter.writeOpaque(%s);' % dest
597 print ' trace::localWriter.endArg();'
598 print ' trace::localWriter.beginArg(1);'
599 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
600 print ' trace::localWriter.endArg();'
601 print ' trace::localWriter.beginArg(2);'
602 print ' trace::localWriter.writeUInt(%s);' % length
603 print ' trace::localWriter.endArg();'
604 print ' trace::localWriter.endEnter();'
605 print ' trace::localWriter.beginLeave(__call);'
606 print ' trace::localWriter.endLeave();'