return "Wrap" + interface.expr
+
class ComplexValueSerializer(stdapi.OnceVisitor):
'''Type visitors which generates serialization functions for
complex types.
self.visit(const.type)
def visitStruct(self, struct):
- for type, name in struct.members:
- self.visit(type)
- print 'static void _write__%s(const %s &value) {' % (struct.tag, struct.expr)
- print ' static const char * members[%u] = {' % (len(struct.members),)
+ print 'static const char * _struct%s_members[%u] = {' % (struct.tag, len(struct.members))
for type, name, in struct.members:
- print ' "%s",' % (name,)
- print ' };'
- print ' static const trace::StructSig sig = {'
- print ' %u, "%s", %u, members' % (struct.id, struct.name, len(struct.members))
- print ' };'
- print ' trace::localWriter.beginStruct(&sig);'
- for type, name in struct.members:
- self.serializer.visit(type, 'value.%s' % (name,))
- print ' trace::localWriter.endStruct();'
- print '}'
+ if name is None:
+ print ' "",'
+ else:
+ print ' "%s",' % (name,)
+ print '};'
+ print 'static const trace::StructSig _struct%s_sig = {' % (struct.tag,)
+ if struct.name is None:
+ structName = '""'
+ else:
+ structName = '"%s"' % struct.name
+ print ' %u, %s, %u, _struct%s_members' % (struct.id, structName, len(struct.members), struct.tag)
+ print '};'
print
def visitArray(self, array):
def visitEnum(self, enum):
print 'static const trace::EnumValue _enum%s_values[] = {' % (enum.tag)
for value in enum.values:
- print ' {"%s", %s},' % (value, value)
+ print ' {"%s", %s},' % (value, value)
print '};'
print
print 'static const trace::EnumSig _enum%s_sig = {' % (enum.tag)
- print ' %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag)
+ print ' %u, %u, _enum%s_values' % (enum.id, len(enum.values), enum.tag)
print '};'
print
def visitBitmask(self, bitmask):
print 'static const trace::BitmaskFlag _bitmask%s_flags[] = {' % (bitmask.tag)
for value in bitmask.values:
- print ' {"%s", %s},' % (value, value)
+ print ' {"%s", %s},' % (value, value)
print '};'
print
print 'static const trace::BitmaskSig _bitmask%s_sig = {' % (bitmask.tag)
- print ' %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
+ print ' %u, %u, _bitmask%s_flags' % (bitmask.id, len(bitmask.values), bitmask.tag)
print '};'
print
print
-class ValueSerializer(stdapi.Visitor):
+class ValueSerializer(stdapi.Visitor, stdapi.ExpanderMixin):
'''Visitor which generates code to serialize any type.
Simple types are serialized inline here, whereas the serialization of
print ' trace::localWriter.write%s(%s);' % (literal.kind, instance)
def visitString(self, string, instance):
- if string.kind == 'String':
+ if not string.wide:
cast = 'const char *'
- elif string.kind == 'WString':
- cast = 'const wchar_t *'
+ suffix = 'String'
else:
- assert False
+ cast = 'const wchar_t *'
+ suffix = 'WString'
if cast != string.expr:
# reinterpret_cast is necessary for GLubyte * <=> char *
instance = 'reinterpret_cast<%s>(%s)' % (cast, instance)
if string.length is not None:
- length = ', %s' % string.length
+ length = ', %s' % self.expand(string.length)
else:
length = ''
- print ' trace::localWriter.write%s(%s%s);' % (string.kind, instance, length)
+ print ' trace::localWriter.write%s(%s%s);' % (suffix, instance, length)
def visitConst(self, const, instance):
self.visit(const.type, instance)
def visitStruct(self, struct, instance):
- print ' _write__%s(%s);' % (struct.tag, instance)
+ print ' trace::localWriter.beginStruct(&_struct%s_sig);' % (struct.tag,)
+ for member in struct.members:
+ self.visitMember(member, instance)
+ print ' trace::localWriter.endStruct();'
def visitArray(self, array, instance):
length = '_c' + array.type.tag
index = '_i' + array.type.tag
+ array_length = self.expand(array.length)
print ' if (%s) {' % instance
- print ' size_t %s = %s > 0 ? %s : 0;' % (length, array.length, array.length)
+ print ' size_t %s = %s > 0 ? %s : 0;' % (length, array_length, array_length)
print ' trace::localWriter.beginArray(%s);' % length
print ' for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
print ' trace::localWriter.beginElement();'
- self.visit(array.type, '(%s)[%s]' % (instance, index))
+ self.visitElement(index, array.type, '(%s)[%s]' % (instance, index))
print ' trace::localWriter.endElement();'
print ' }'
print ' trace::localWriter.endArray();'
print ' }'
def visitBlob(self, blob, instance):
- print ' trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size)
+ print ' trace::localWriter.writeBlob(%s, %s);' % (instance, self.expand(blob.size))
def visitEnum(self, enum, instance):
print ' trace::localWriter.writeEnum(&_enum%s_sig, %s);' % (enum.tag, instance)
if polymorphic.contextLess:
print ' _write__%s(%s, %s);' % (polymorphic.tag, polymorphic.switchExpr, instance)
else:
- print ' switch (%s) {' % polymorphic.switchExpr
+ switchExpr = self.expand(polymorphic.switchExpr)
+ print ' switch (%s) {' % switchExpr
for cases, type in polymorphic.iterSwitch():
for case in cases:
print ' %s:' % case
- self.visit(type, 'static_cast<%s>(%s)' % (type, instance))
+ caseInstance = instance
+ if type.expr is not None:
+ caseInstance = 'static_cast<%s>(%s)' % (type, caseInstance)
+ self.visit(type, caseInstance)
print ' break;'
+ if polymorphic.defaultType is None:
+ print r' default:'
+ print r' os::log("apitrace: warning: %%s: unexpected polymorphic case %%i\n", __FUNCTION__, (int)%s);' % (switchExpr,)
+ print r' trace::localWriter.writeNull();'
+ print r' break;'
print ' }'
self.needsWrapping = True
-class ValueWrapper(stdapi.Traverser):
+class ValueWrapper(stdapi.Traverser, stdapi.ExpanderMixin):
'''Type visitor which will generate the code to wrap an instance.
Wrapping is necessary mostly for interfaces, however interface pointers can
'''
def visitStruct(self, struct, instance):
- for type, name in struct.members:
- self.visit(type, "(%s).%s" % (instance, name))
+ for member in struct.members:
+ self.visitMember(member, instance)
def visitArray(self, array, instance):
+ array_length = self.expand(array.length)
print " if (%s) {" % instance
- print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array.length
- self.visit(array.type, instance + "[_i]")
+ print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
+ self.visitElement('_i', array.type, instance + "[_i]")
print " }"
print " }"
elem_type = pointer.type.mutable()
if isinstance(elem_type, stdapi.Interface):
self.visitInterfacePointer(elem_type, instance)
+ elif isinstance(elem_type, stdapi.Alias) and isinstance(elem_type.type, stdapi.Interface):
+ self.visitInterfacePointer(elem_type.type, instance)
else:
self.visitPointer(pointer, instance)
allocated = False
+ def visitStruct(self, struct, instance):
+ if not self.allocated:
+ # Argument is constant. We need to create a non const
+ print ' {'
+ print " %s * _t = static_cast<%s *>(alloca(sizeof *_t));" % (struct, struct)
+ print ' *_t = %s;' % (instance,)
+ assert instance.startswith('*')
+ print ' %s = _t;' % (instance[1:],)
+ instance = '*_t'
+ self.allocated = True
+ try:
+ return ValueWrapper.visitStruct(self, struct, instance)
+ finally:
+ print ' }'
+ else:
+ return ValueWrapper.visitStruct(self, struct, instance)
+
def visitArray(self, array, instance):
if self.allocated or isinstance(instance, stdapi.Interface):
return ValueWrapper.visitArray(self, array, instance)
+ array_length = self.expand(array.length)
elem_type = array.type.mutable()
- print " if (%s && %s) {" % (instance, array.length)
- print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array.length)
- print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array.length
+ print " if (%s && %s) {" % (instance, array_length)
+ print " %s * _t = static_cast<%s *>(alloca(%s * sizeof *_t));" % (elem_type, elem_type, array_length)
+ print " for (size_t _i = 0, _s = %s; _i < _s; ++_i) {" % array_length
print " _t[_i] = %s[_i];" % instance
self.allocated = True
self.visit(array.type, "_t[_i]")
self.header(api)
# Includes
- for header in api.headers:
- print header
+ for module in api.modules:
+ for header in module.headers:
+ print header
print
# Generate the serializer functions
# Function wrappers
self.interface = None
self.base = None
- map(self.traceFunctionDecl, api.functions)
- map(self.traceFunctionImpl, api.functions)
+ for function in api.getAllFunctions():
+ self.traceFunctionDecl(function)
+ for function in api.getAllFunctions():
+ self.traceFunctionImpl(function)
print
self.footer(api)
print '#else'
print '# include <alloca.h> // alloca'
print '#endif'
+ print
+ print '#include "trace.hpp"'
+ print
def footer(self, api):
pass
print function.prototype() + ' {'
if function.type is not stdapi.Void:
print ' %s _result;' % function.type
+
+ # No-op if tracing is disabled
+ print ' if (!trace::isTracingEnabled()) {'
+ Tracer.invokeFunction(self, function)
+ if function.type is not stdapi.Void:
+ print ' return _result;'
+ else:
+ print ' return;'
+ print ' }'
+
self.traceFunctionImplBody(function)
if function.type is not stdapi.Void:
print ' return _result;'
self.invokeFunction(function)
if not function.internal:
print ' trace::localWriter.beginLeave(_call);'
+ print ' if (%s) {' % self.wasFunctionSuccessful(function)
for arg in function.args:
if arg.output:
self.serializeArg(function, arg)
self.wrapArg(function, arg)
+ print ' }'
if function.type is not stdapi.Void:
self.serializeRet(function, "_result")
print ' trace::localWriter.endLeave();'
dispatch = prefix + function.name + suffix
print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
+ def wasFunctionSuccessful(self, function):
+ if function.type is stdapi.Void:
+ return 'true'
+ if str(function.type) == 'HRESULT':
+ return 'SUCCEEDED(_result)'
+ return 'true'
+
def serializeArg(self, function, arg):
print ' trace::localWriter.beginArg(%u);' % (arg.index,)
self.serializeArgValue(function, arg)
#print "private:"
for type, name, value in self.enumWrapperInterfaceVariables(interface):
print ' %s %s;' % (type, name)
+ for i in range(64):
+ print r' virtual void _dummy%i(void) const {' % i
+ print r' os::log("error: %s: unexpected virtual method\n");' % interface.name
+ print r' os::abort();'
+ print r' }'
print "};"
print
self.invokeMethod(interface, base, method)
print ' trace::localWriter.beginLeave(_call);'
+
+ print ' if (%s) {' % self.wasFunctionSuccessful(method)
for arg in method.args:
if arg.output:
self.serializeArg(method, arg)
self.wrapArg(method, arg)
+ print ' }'
if method.type is not stdapi.Void:
self.serializeRet(method, '_result')
print ' trace::localWriter.endEnter();'
print ' trace::localWriter.beginLeave(_call);'
print ' trace::localWriter.endLeave();'
+
+ def fake_call(self, function, args):
+ print ' unsigned _fake_call = trace::localWriter.beginEnter(&_%s_sig);' % (function.name,)
+ for arg, instance in zip(function.args, args):
+ assert not arg.output
+ print ' trace::localWriter.beginArg(%u);' % (arg.index,)
+ self.serializeValue(arg.type, instance)
+ print ' trace::localWriter.endArg();'
+ print ' trace::localWriter.endEnter();'
+ print ' trace::localWriter.beginLeave(_fake_call);'
+ print ' trace::localWriter.endLeave();'