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.length is not None:
152 print ' trace::localWriter.writeString((const char *)%s, %s);' % (instance, string.length)
154 print ' trace::localWriter.writeString((const char *)%s);' % instance
156 def visitConst(self, const, instance):
157 self.visit(const.type, instance)
159 def visitStruct(self, struct, instance):
160 print ' _write__%s(%s);' % (struct.tag, instance)
162 def visitArray(self, array, instance):
163 length = '__c' + array.type.tag
164 index = '__i' + array.type.tag
165 print ' if (%s) {' % instance
166 print ' size_t %s = %s;' % (length, array.length)
167 print ' trace::localWriter.beginArray(%s);' % length
168 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
169 print ' trace::localWriter.beginElement();'
170 self.visit(array.type, '(%s)[%s]' % (instance, index))
171 print ' trace::localWriter.endElement();'
173 print ' trace::localWriter.endArray();'
175 print ' trace::localWriter.writeNull();'
178 def visitBlob(self, blob, instance):
179 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size)
181 def visitEnum(self, enum, instance):
182 print ' trace::localWriter.writeEnum(&__enum%s_sig, %s);' % (enum.tag, instance)
184 def visitBitmask(self, bitmask, instance):
185 print ' trace::localWriter.writeBitmask(&__bitmask%s_sig, %s);' % (bitmask.tag, instance)
187 def visitPointer(self, pointer, instance):
188 print ' if (%s) {' % instance
189 print ' trace::localWriter.beginArray(1);'
190 print ' trace::localWriter.beginElement();'
191 self.visit(pointer.type, "*" + instance)
192 print ' trace::localWriter.endElement();'
193 print ' trace::localWriter.endArray();'
195 print ' trace::localWriter.writeNull();'
198 def visitIntPointer(self, pointer, instance):
199 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
201 def visitLinearPointer(self, pointer, instance):
202 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
204 def visitHandle(self, handle, instance):
205 self.visit(handle.type, instance)
207 def visitAlias(self, alias, instance):
208 self.visit(alias.type, instance)
210 def visitOpaque(self, opaque, instance):
211 print ' trace::localWriter.writeOpaque((const void *)%s);' % instance
213 def visitInterface(self, interface, instance):
214 print ' trace::localWriter.writeOpaque((const void *)&%s);' % instance
216 def visitPolymorphic(self, polymorphic, instance):
217 print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
220 class ValueWrapper(stdapi.Visitor):
221 '''Type visitor which will generate the code to wrap an instance.
223 Wrapping is necessary mostly for interfaces, however interface pointers can
224 appear anywhere inside complex types.
227 def visitVoid(self, type, instance):
228 raise NotImplementedError
230 def visitLiteral(self, type, instance):
233 def visitString(self, type, instance):
236 def visitConst(self, type, instance):
239 def visitStruct(self, struct, instance):
240 for type, name in struct.members:
241 self.visit(type, "(%s).%s" % (instance, name))
243 def visitArray(self, array, instance):
244 # XXX: actually it is possible to return an array of pointers
247 def visitBlob(self, blob, instance):
250 def visitEnum(self, enum, instance):
253 def visitBitmask(self, bitmask, instance):
256 def visitPointer(self, pointer, instance):
257 print " if (%s) {" % instance
258 self.visit(pointer.type, "*" + instance)
261 def visitIntPointer(self, pointer, instance):
264 def visitLinearPointer(self, pointer, instance):
267 def visitHandle(self, handle, instance):
268 self.visit(handle.type, instance)
270 def visitAlias(self, alias, instance):
271 self.visit(alias.type, instance)
273 def visitOpaque(self, opaque, instance):
276 def visitInterface(self, interface, instance):
277 assert instance.startswith('*')
278 instance = instance[1:]
279 print " if (%s) {" % instance
280 print " %s = new %s(%s);" % (instance, getWrapperInterfaceName(interface), instance)
283 def visitPolymorphic(self, type, instance):
284 # XXX: There might be polymorphic values that need wrapping in the future
288 class ValueUnwrapper(ValueWrapper):
289 '''Reverse of ValueWrapper.'''
291 def visitInterface(self, interface, instance):
292 assert instance.startswith('*')
293 instance = instance[1:]
294 print " if (%s) {" % instance
295 print " %s = static_cast<%s *>(%s)->m_pInstance;" % (instance, getWrapperInterfaceName(interface), instance)
300 '''Base class to orchestrate the code generation of API tracing.'''
305 def serializerFactory(self):
306 '''Create a serializer.
308 Can be overriden by derived classes to inject their own serialzer.
311 return ValueSerializer()
313 def trace_api(self, api):
319 for header in api.headers:
323 # Generate the serializer functions
324 types = api.all_types()
325 visitor = ComplexValueSerializer(self.serializerFactory())
326 map(visitor.visit, types)
330 interfaces = [type for type in types if isinstance(type, stdapi.Interface)]
331 map(self.declareWrapperInterface, interfaces)
332 map(self.implementWrapperInterface, interfaces)
336 map(self.traceFunctionDecl, api.functions)
337 map(self.traceFunctionImpl, api.functions)
342 def header(self, api):
345 def footer(self, api):
348 def traceFunctionDecl(self, function):
349 # Per-function declarations
352 print 'static const char * __%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
354 print 'static const char ** __%s_args = NULL;' % (function.name,)
355 print 'static const trace::FunctionSig __%s_sig = {%u, "%s", %u, __%s_args};' % (function.name, function.id, function.name, len(function.args), function.name)
358 def isFunctionPublic(self, function):
361 def traceFunctionImpl(self, function):
362 if self.isFunctionPublic(function):
363 print 'extern "C" PUBLIC'
365 print 'extern "C" PRIVATE'
366 print function.prototype() + ' {'
367 if function.type is not stdapi.Void:
368 print ' %s __result;' % function.type
369 self.traceFunctionImplBody(function)
370 if function.type is not stdapi.Void:
371 self.wrapRet(function, "__result")
372 print ' return __result;'
376 def traceFunctionImplBody(self, function):
377 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
378 for arg in function.args:
380 self.unwrapArg(function, arg)
381 self.serializeArg(function, arg)
382 print ' trace::localWriter.endEnter();'
383 self.invokeFunction(function)
384 print ' trace::localWriter.beginLeave(__call);'
385 for arg in function.args:
387 self.serializeArg(function, arg)
388 self.wrapArg(function, arg)
389 if function.type is not stdapi.Void:
390 self.serializeRet(function, "__result")
391 print ' trace::localWriter.endLeave();'
393 def invokeFunction(self, function, prefix='__', suffix=''):
394 if function.type is stdapi.Void:
397 result = '__result = '
398 dispatch = prefix + function.name + suffix
399 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
401 def serializeArg(self, function, arg):
402 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
403 self.serializeArgValue(function, arg)
404 print ' trace::localWriter.endArg();'
406 def serializeArgValue(self, function, arg):
407 self.serializeValue(arg.type, arg.name)
409 def wrapArg(self, function, arg):
410 self.wrapValue(arg.type, arg.name)
412 def unwrapArg(self, function, arg):
413 self.unwrapValue(arg.type, arg.name)
415 def serializeRet(self, function, instance):
416 print ' trace::localWriter.beginReturn();'
417 self.serializeValue(function.type, instance)
418 print ' trace::localWriter.endReturn();'
420 def serializeValue(self, type, instance):
421 serializer = self.serializerFactory()
422 serializer.visit(type, instance)
424 def wrapRet(self, function, instance):
425 self.wrapValue(function.type, instance)
427 def unwrapRet(self, function, instance):
428 self.unwrapValue(function.type, instance)
430 def wrapValue(self, type, instance):
431 visitor = ValueWrapper()
432 visitor.visit(type, instance)
434 def unwrapValue(self, type, instance):
435 visitor = ValueUnwrapper()
436 visitor.visit(type, instance)
438 def declareWrapperInterface(self, interface):
439 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
442 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
443 print " virtual ~%s();" % getWrapperInterfaceName(interface)
445 for method in interface.iterMethods():
446 print " " + method.prototype() + ";"
448 self.declareWrapperInterfaceVariables(interface)
452 def declareWrapperInterfaceVariables(self, interface):
454 print " %s * m_pInstance;" % (interface.name,)
456 def implementWrapperInterface(self, interface):
457 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
458 print ' m_pInstance = pInstance;'
461 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
464 for method in interface.iterMethods():
465 self.implementWrapperInterfaceMethod(interface, method)
468 def implementWrapperInterfaceMethod(self, interface, method):
469 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
470 if method.type is not stdapi.Void:
471 print ' %s __result;' % method.type
473 self.implementWrapperInterfaceMethodBody(interface, method)
475 if method.type is not stdapi.Void:
476 print ' return __result;'
480 def implementWrapperInterfaceMethodBody(self, interface, method):
481 print ' static const char * __args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
482 print ' static const trace::FunctionSig __sig = {%u, "%s", %u, __args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1)
483 print ' unsigned __call = trace::localWriter.beginEnter(&__sig);'
484 print ' trace::localWriter.beginArg(0);'
485 print ' trace::localWriter.writeOpaque((const void *)m_pInstance);'
486 print ' trace::localWriter.endArg();'
487 for arg in method.args:
489 self.unwrapArg(method, arg)
490 self.serializeArg(method, arg)
491 print ' trace::localWriter.endEnter();'
493 self.invokeMethod(interface, method)
495 print ' trace::localWriter.beginLeave(__call);'
496 for arg in method.args:
498 self.serializeArg(method, arg)
499 self.wrapArg(method, arg)
500 if method.type is not stdapi.Void:
501 print ' trace::localWriter.beginReturn();'
502 self.serializeValue(method.type, "__result")
503 print ' trace::localWriter.endReturn();'
504 self.wrapValue(method.type, '__result')
505 print ' trace::localWriter.endLeave();'
506 if method.name == 'QueryInterface':
507 print ' if (ppvObj && *ppvObj) {'
508 print ' if (*ppvObj == m_pInstance) {'
509 print ' *ppvObj = this;'
511 for iface in self.api.interfaces:
512 print r' else if (riid == IID_%s) {' % iface.name
513 print r' *ppvObj = new Wrap%s((%s *) *ppvObj);' % (iface.name, iface.name)
516 print r' os::log("apitrace: warning: 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",'
517 print r' riid.Data1, riid.Data2, riid.Data3,'
518 print r' riid.Data4[0],'
519 print r' riid.Data4[1],'
520 print r' riid.Data4[2],'
521 print r' riid.Data4[3],'
522 print r' riid.Data4[4],'
523 print r' riid.Data4[5],'
524 print r' riid.Data4[6],'
525 print r' riid.Data4[7]);'
528 if method.name == 'Release':
529 assert method.type is not stdapi.Void
530 print ' if (!__result)'
531 print ' delete this;'
533 def invokeMethod(self, interface, method):
534 if method.type is stdapi.Void:
537 result = '__result = '
538 print ' %sm_pInstance->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
540 def emit_memcpy(self, dest, src, length):
541 print ' unsigned __call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
542 print ' trace::localWriter.beginArg(0);'
543 print ' trace::localWriter.writeOpaque(%s);' % dest
544 print ' trace::localWriter.endArg();'
545 print ' trace::localWriter.beginArg(1);'
546 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
547 print ' trace::localWriter.endArg();'
548 print ' trace::localWriter.beginArg(2);'
549 print ' trace::localWriter.writeUInt(%s);' % length
550 print ' trace::localWriter.endArg();'
551 print ' trace::localWriter.endEnter();'
552 print ' trace::localWriter.beginLeave(__call);'
553 print ' trace::localWriter.endLeave();'