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 " if (%s) {" % instance
305 print " %s = static_cast<%s *>(%s)->m_pInstance;" % (instance, getWrapperInterfaceName(interface), instance)
310 '''Base class to orchestrate the code generation of API tracing.'''
315 def serializerFactory(self):
316 '''Create a serializer.
318 Can be overriden by derived classes to inject their own serialzer.
321 return ValueSerializer()
323 def trace_api(self, api):
329 for header in api.headers:
333 # Generate the serializer functions
334 types = api.getAllTypes()
335 visitor = ComplexValueSerializer(self.serializerFactory())
336 map(visitor.visit, types)
340 interfaces = api.getAllInterfaces()
341 map(self.declareWrapperInterface, interfaces)
342 map(self.implementWrapperInterface, interfaces)
346 map(self.traceFunctionDecl, api.functions)
347 map(self.traceFunctionImpl, api.functions)
352 def header(self, api):
355 def footer(self, api):
358 def traceFunctionDecl(self, function):
359 # Per-function declarations
362 print 'static const char * __%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
364 print 'static const char ** __%s_args = NULL;' % (function.name,)
365 print 'static const trace::FunctionSig __%s_sig = {%u, "%s", %u, __%s_args};' % (function.name, function.id, function.name, len(function.args), function.name)
368 def isFunctionPublic(self, function):
371 def traceFunctionImpl(self, function):
372 if self.isFunctionPublic(function):
373 print 'extern "C" PUBLIC'
375 print 'extern "C" PRIVATE'
376 print function.prototype() + ' {'
377 if function.type is not stdapi.Void:
378 print ' %s __result;' % function.type
379 self.traceFunctionImplBody(function)
380 if function.type is not stdapi.Void:
381 self.wrapRet(function, "__result")
382 print ' return __result;'
386 def traceFunctionImplBody(self, function):
387 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
388 for arg in function.args:
390 self.unwrapArg(function, arg)
391 self.serializeArg(function, arg)
392 print ' trace::localWriter.endEnter();'
393 self.invokeFunction(function)
394 print ' trace::localWriter.beginLeave(__call);'
395 for arg in function.args:
397 self.serializeArg(function, arg)
398 self.wrapArg(function, arg)
399 if function.type is not stdapi.Void:
400 self.serializeRet(function, "__result")
401 print ' trace::localWriter.endLeave();'
403 def invokeFunction(self, function, prefix='__', suffix=''):
404 if function.type is stdapi.Void:
407 result = '__result = '
408 dispatch = prefix + function.name + suffix
409 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
411 def serializeArg(self, function, arg):
412 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
413 self.serializeArgValue(function, arg)
414 print ' trace::localWriter.endArg();'
416 def serializeArgValue(self, function, arg):
417 self.serializeValue(arg.type, arg.name)
419 def wrapArg(self, function, arg):
420 self.wrapValue(arg.type, arg.name)
422 def unwrapArg(self, function, arg):
423 self.unwrapValue(arg.type, arg.name)
425 def serializeRet(self, function, instance):
426 print ' trace::localWriter.beginReturn();'
427 self.serializeValue(function.type, instance)
428 print ' trace::localWriter.endReturn();'
430 def serializeValue(self, type, instance):
431 serializer = self.serializerFactory()
432 serializer.visit(type, instance)
434 def wrapRet(self, function, instance):
435 self.wrapValue(function.type, instance)
437 def unwrapRet(self, function, instance):
438 self.unwrapValue(function.type, instance)
440 def wrapValue(self, type, instance):
441 visitor = ValueWrapper()
442 visitor.visit(type, instance)
444 def unwrapValue(self, type, instance):
445 visitor = ValueUnwrapper()
446 visitor.visit(type, instance)
448 def declareWrapperInterface(self, interface):
449 print "class %s : public %s " % (getWrapperInterfaceName(interface), interface.name)
452 print " %s(%s * pInstance);" % (getWrapperInterfaceName(interface), interface.name)
453 print " virtual ~%s();" % getWrapperInterfaceName(interface)
455 for method in interface.iterMethods():
456 print " " + method.prototype() + ";"
458 self.declareWrapperInterfaceVariables(interface)
462 def declareWrapperInterfaceVariables(self, interface):
464 print " %s * m_pInstance;" % (interface.name,)
466 def implementWrapperInterface(self, interface):
467 print '%s::%s(%s * pInstance) {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface), interface.name)
468 print ' m_pInstance = pInstance;'
471 print '%s::~%s() {' % (getWrapperInterfaceName(interface), getWrapperInterfaceName(interface))
474 for base, method in interface.iterBaseMethods():
475 self.implementWrapperInterfaceMethod(interface, base, method)
478 def implementWrapperInterfaceMethod(self, interface, base, method):
479 print method.prototype(getWrapperInterfaceName(interface) + '::' + method.name) + ' {'
480 if method.type is not stdapi.Void:
481 print ' %s __result;' % method.type
483 self.implementWrapperInterfaceMethodBody(interface, base, method)
485 if method.type is not stdapi.Void:
486 print ' return __result;'
490 def implementWrapperInterfaceMethodBody(self, interface, base, method):
491 print ' static const char * __args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
492 print ' static const trace::FunctionSig __sig = {%u, "%s", %u, __args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1)
493 print ' unsigned __call = trace::localWriter.beginEnter(&__sig);'
494 print ' trace::localWriter.beginArg(0);'
495 print ' trace::localWriter.writeOpaque((const void *)m_pInstance);'
496 print ' trace::localWriter.endArg();'
498 from specs.winapi import REFIID
499 from specs.stdapi import Pointer, Opaque
502 for arg in method.args:
504 self.unwrapArg(method, arg)
505 self.serializeArg(method, arg)
506 if arg.type is REFIID:
508 print ' trace::localWriter.endEnter();'
510 self.invokeMethod(interface, base, method)
512 print ' trace::localWriter.beginLeave(__call);'
513 for arg in method.args:
515 self.serializeArg(method, arg)
516 self.wrapArg(method, arg)
517 if riid is not None and isinstance(arg.type, Pointer):
518 assert isinstance(arg.type.type, Opaque)
519 self.wrapIid(interface, method, riid, arg)
521 if method.type is not stdapi.Void:
522 print ' trace::localWriter.beginReturn();'
523 self.serializeValue(method.type, "__result")
524 print ' trace::localWriter.endReturn();'
525 self.wrapValue(method.type, '__result')
526 print ' trace::localWriter.endLeave();'
527 if method.name == 'Release':
528 assert method.type is not stdapi.Void
529 print ' if (!__result)'
530 print ' delete this;'
532 def wrapIid(self, interface, method, riid, out):
533 print ' if (%s && *%s) {' % (out.name, out.name)
534 print ' if (*%s == m_pInstance) {' % (out.name,)
535 print ' *%s = this;' % (out.name,)
537 for iface in self.api.interfaces:
538 print r' else if (%s == IID_%s) {' % (riid.name, iface.name)
539 print r' *%s = new Wrap%s((%s *) *%s);' % (out.name, iface.name, iface.name, out.name)
542 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",'
543 print r' %s.Data1, %s.Data2, %s.Data3,' % (riid.name, riid.name, riid.name)
544 print r' %s.Data4[0],' % (riid.name,)
545 print r' %s.Data4[1],' % (riid.name,)
546 print r' %s.Data4[2],' % (riid.name,)
547 print r' %s.Data4[3],' % (riid.name,)
548 print r' %s.Data4[4],' % (riid.name,)
549 print r' %s.Data4[5],' % (riid.name,)
550 print r' %s.Data4[6],' % (riid.name,)
551 print r' %s.Data4[7]);' % (riid.name,)
555 def invokeMethod(self, interface, base, method):
556 if method.type is stdapi.Void:
559 result = '__result = '
560 print ' %sstatic_cast<%s *>(m_pInstance)->%s(%s);' % (result, base, method.name, ', '.join([str(arg.name) for arg in method.args]))
562 def emit_memcpy(self, dest, src, length):
563 print ' unsigned __call = trace::localWriter.beginEnter(&trace::memcpy_sig);'
564 print ' trace::localWriter.beginArg(0);'
565 print ' trace::localWriter.writeOpaque(%s);' % dest
566 print ' trace::localWriter.endArg();'
567 print ' trace::localWriter.beginArg(1);'
568 print ' trace::localWriter.writeBlob(%s, %s);' % (src, length)
569 print ' trace::localWriter.endArg();'
570 print ' trace::localWriter.beginArg(2);'
571 print ' trace::localWriter.writeUInt(%s);' % length
572 print ' trace::localWriter.endArg();'
573 print ' trace::localWriter.endEnter();'
574 print ' trace::localWriter.beginLeave(__call);'
575 print ' trace::localWriter.endLeave();'