X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=wrappers%2Ftrace.py;h=506570dca018ed9bc0dde652940cd33babd83fb6;hb=28f65148273ec8fade06a6e5bbfe40017be41dcb;hp=30668365ee3fc27eded75d3f4111f64d0951b0e7;hpb=9115776479fc67fe12cc3f7ccb8da2fd684d2232;p=apitrace diff --git a/wrappers/trace.py b/wrappers/trace.py index 3066836..506570d 100644 --- a/wrappers/trace.py +++ b/wrappers/trace.py @@ -39,6 +39,7 @@ def getWrapperInterfaceName(interface): return "Wrap" + interface.expr + class ComplexValueSerializer(stdapi.OnceVisitor): '''Type visitors which generates serialization functions for complex types. @@ -63,21 +64,20 @@ class ComplexValueSerializer(stdapi.OnceVisitor): 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): @@ -89,22 +89,22 @@ class ComplexValueSerializer(stdapi.OnceVisitor): 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 @@ -150,7 +150,7 @@ class ComplexValueSerializer(stdapi.OnceVisitor): 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 @@ -172,7 +172,7 @@ class ValueSerializer(stdapi.Visitor): # 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);' % (suffix, instance, length) @@ -181,17 +181,21 @@ class ValueSerializer(stdapi.Visitor): 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();' @@ -200,7 +204,7 @@ class ValueSerializer(stdapi.Visitor): 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) @@ -247,12 +251,21 @@ class ValueSerializer(stdapi.Visitor): 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 ' }' @@ -272,7 +285,7 @@ class WrapDecider(stdapi.Traverser): 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 @@ -280,13 +293,14 @@ class ValueWrapper(stdapi.Traverser): ''' 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 " }" @@ -299,6 +313,8 @@ class ValueWrapper(stdapi.Traverser): 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) @@ -320,13 +336,31 @@ class ValueUnwrapper(ValueWrapper): 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]") @@ -365,8 +399,9 @@ class Tracer: 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 @@ -381,8 +416,10 @@ class Tracer: # 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) @@ -452,10 +489,12 @@ class Tracer: 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();' @@ -470,6 +509,13 @@ class Tracer: 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) @@ -609,10 +655,13 @@ class Tracer: 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')