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 interface_wrap_name(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 visitHandle(self, handle):
109 self.visit(handle.type)
111 def visitAlias(self, alias):
112 self.visit(alias.type)
114 def visitOpaque(self, opaque):
117 def visitInterface(self, interface):
118 print "class %s : public %s " % (interface_wrap_name(interface), interface.name)
121 print " %s(%s * pInstance);" % (interface_wrap_name(interface), interface.name)
122 print " virtual ~%s();" % interface_wrap_name(interface)
124 for method in interface.iterMethods():
125 print " " + method.prototype() + ";"
128 print " %s * m_pInstance;" % (interface.name,)
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.length is not None:
158 print ' trace::localWriter.writeString((const char *)%s, %s);' % (instance, string.length)
160 print ' trace::localWriter.writeString((const char *)%s);' % instance
162 def visitConst(self, const, instance):
163 self.visit(const.type, instance)
165 def visitStruct(self, struct, instance):
166 print ' _write__%s(%s);' % (struct.tag, instance)
168 def visitArray(self, array, instance):
169 length = '__c' + array.type.tag
170 index = '__i' + array.type.tag
171 print ' if (%s) {' % instance
172 print ' size_t %s = %s;' % (length, array.length)
173 print ' trace::localWriter.beginArray(%s);' % length
174 print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
175 print ' trace::localWriter.beginElement();'
176 self.visit(array.type, '(%s)[%s]' % (instance, index))
177 print ' trace::localWriter.endElement();'
179 print ' trace::localWriter.endArray();'
181 print ' trace::localWriter.writeNull();'
184 def visitBlob(self, blob, instance):
185 print ' trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size)
187 def visitEnum(self, enum, instance):
188 print ' trace::localWriter.writeEnum(&__enum%s_sig, %s);' % (enum.tag, instance)
190 def visitBitmask(self, bitmask, instance):
191 print ' trace::localWriter.writeBitmask(&__bitmask%s_sig, %s);' % (bitmask.tag, instance)
193 def visitPointer(self, pointer, instance):
194 print ' if (%s) {' % instance
195 print ' trace::localWriter.beginArray(1);'
196 print ' trace::localWriter.beginElement();'
197 self.visit(pointer.type, "*" + instance)
198 print ' trace::localWriter.endElement();'
199 print ' trace::localWriter.endArray();'
201 print ' trace::localWriter.writeNull();'
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 visitHandle(self, handle, instance):
262 self.visit(handle.type, instance)
264 def visitAlias(self, alias, instance):
265 self.visit(alias.type, instance)
267 def visitOpaque(self, opaque, instance):
270 def visitInterface(self, interface, instance):
271 assert instance.startswith('*')
272 instance = instance[1:]
273 print " if (%s) {" % instance
274 print " %s = new %s(%s);" % (instance, interface_wrap_name(interface), instance)
277 def visitPolymorphic(self, type, instance):
278 # XXX: There might be polymorphic values that need wrapping in the future
282 class ValueUnwrapper(ValueWrapper):
283 '''Reverse of ValueWrapper.'''
285 def visitInterface(self, interface, instance):
286 assert instance.startswith('*')
287 instance = instance[1:]
288 print " if (%s) {" % instance
289 print " %s = static_cast<%s *>(%s)->m_pInstance;" % (instance, interface_wrap_name(interface), instance)
294 '''Base class to orchestrate the code generation of API tracing.'''
299 def serializerFactory(self):
300 '''Create a serializer.
302 Can be overriden by derived classes to inject their own serialzer.
305 return ValueSerializer()
307 def trace_api(self, api):
313 for header in api.headers:
317 # Generate the serializer functions
318 types = api.all_types()
319 visitor = ComplexValueSerializer(self.serializerFactory())
320 map(visitor.visit, types)
324 interfaces = [type for type in types if isinstance(type, stdapi.Interface)]
325 map(self.traceInterfaceImpl, interfaces)
329 map(self.traceFunctionDecl, api.functions)
330 map(self.traceFunctionImpl, api.functions)
335 def header(self, api):
338 def footer(self, api):
341 def traceFunctionDecl(self, function):
342 # Per-function declarations
345 print 'static const char * __%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args]))
347 print 'static const char ** __%s_args = NULL;' % (function.name,)
348 print 'static const trace::FunctionSig __%s_sig = {%u, "%s", %u, __%s_args};' % (function.name, function.id, function.name, len(function.args), function.name)
351 def isFunctionPublic(self, function):
354 def traceFunctionImpl(self, function):
355 if self.isFunctionPublic(function):
356 print 'extern "C" PUBLIC'
358 print 'extern "C" PRIVATE'
359 print function.prototype() + ' {'
360 if function.type is not stdapi.Void:
361 print ' %s __result;' % function.type
362 self.traceFunctionImplBody(function)
363 if function.type is not stdapi.Void:
364 self.wrapRet(function, "__result")
365 print ' return __result;'
369 def traceFunctionImplBody(self, function):
370 print ' unsigned __call = trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
371 for arg in function.args:
373 self.unwrapArg(function, arg)
374 self.serializeArg(function, arg)
375 print ' trace::localWriter.endEnter();'
376 self.invokeFunction(function)
377 print ' trace::localWriter.beginLeave(__call);'
378 for arg in function.args:
380 self.serializeArg(function, arg)
381 self.wrapArg(function, arg)
382 if function.type is not stdapi.Void:
383 self.serializeRet(function, "__result")
384 print ' trace::localWriter.endLeave();'
386 def invokeFunction(self, function, prefix='__', suffix=''):
387 if function.type is stdapi.Void:
390 result = '__result = '
391 dispatch = prefix + function.name + suffix
392 print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
394 def serializeArg(self, function, arg):
395 print ' trace::localWriter.beginArg(%u);' % (arg.index,)
396 self.serializeArgValue(function, arg)
397 print ' trace::localWriter.endArg();'
399 def serializeArgValue(self, function, arg):
400 self.serializeValue(arg.type, arg.name)
402 def wrapArg(self, function, arg):
403 self.wrapValue(arg.type, arg.name)
405 def unwrapArg(self, function, arg):
406 self.unwrapValue(arg.type, arg.name)
408 def serializeRet(self, function, instance):
409 print ' trace::localWriter.beginReturn();'
410 self.serializeValue(function.type, instance)
411 print ' trace::localWriter.endReturn();'
413 def serializeValue(self, type, instance):
414 serializer = self.serializerFactory()
415 serializer.visit(type, instance)
417 def wrapRet(self, function, instance):
418 self.wrapValue(function.type, instance)
420 def unwrapRet(self, function, instance):
421 self.unwrapValue(function.type, instance)
423 def wrapValue(self, type, instance):
424 visitor = ValueWrapper()
425 visitor.visit(type, instance)
427 def unwrapValue(self, type, instance):
428 visitor = ValueUnwrapper()
429 visitor.visit(type, instance)
431 def traceInterfaceImpl(self, interface):
432 print '%s::%s(%s * pInstance) {' % (interface_wrap_name(interface), interface_wrap_name(interface), interface.name)
433 print ' m_pInstance = pInstance;'
436 print '%s::~%s() {' % (interface_wrap_name(interface), interface_wrap_name(interface))
439 for method in interface.iterMethods():
440 self.traceMethod(interface, method)
443 def traceMethod(self, interface, method):
444 print method.prototype(interface_wrap_name(interface) + '::' + method.name) + ' {'
445 print ' static const char * __args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
446 print ' static const trace::FunctionSig __sig = {%u, "%s", %u, __args};' % (method.id, interface.name + '::' + method.name, len(method.args) + 1)
447 print ' unsigned __call = trace::localWriter.beginEnter(&__sig);'
448 print ' trace::localWriter.beginArg(0);'
449 print ' trace::localWriter.writeOpaque((const void *)m_pInstance);'
450 print ' trace::localWriter.endArg();'
451 for arg in method.args:
453 self.unwrapArg(method, arg)
454 self.serializeArg(method, arg)
455 if method.type is stdapi.Void:
458 print ' %s __result;' % method.type
459 result = '__result = '
460 print ' trace::localWriter.endEnter();'
461 print ' %sm_pInstance->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
462 print ' trace::localWriter.beginLeave(__call);'
463 for arg in method.args:
465 self.serializeArg(method, arg)
466 self.wrapArg(method, arg)
467 if method.type is not stdapi.Void:
468 print ' trace::localWriter.beginReturn();'
469 self.serializeValue(method.type, "__result")
470 print ' trace::localWriter.endReturn();'
471 self.wrapValue(method.type, '__result')
472 print ' trace::localWriter.endLeave();'
473 if method.name == 'QueryInterface':
474 print ' if (ppvObj && *ppvObj) {'
475 print ' if (*ppvObj == m_pInstance) {'
476 print ' *ppvObj = this;'
478 for iface in self.api.interfaces:
479 print r' else if (riid == IID_%s) {' % iface.name
480 print r' *ppvObj = new Wrap%s((%s *) *ppvObj);' % (iface.name, iface.name)
483 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",'
484 print r' riid.Data1, riid.Data2, riid.Data3,'
485 print r' riid.Data4[0],'
486 print r' riid.Data4[1],'
487 print r' riid.Data4[2],'
488 print r' riid.Data4[3],'
489 print r' riid.Data4[4],'
490 print r' riid.Data4[5],'
491 print r' riid.Data4[6],'
492 print r' riid.Data4[7]);'
495 if method.name == 'Release':
496 assert method.type is not stdapi.Void
497 print ' if (!__result)'
498 print ' delete this;'
499 if method.type is not stdapi.Void:
500 print ' return __result;'