X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=wrappers%2Ftrace.py;h=4563f454f710822887ad9bd5eaa4de5606db7d4f;hb=4647f208f5a2b87391281e0f1202f66c23943bd9;hp=30668365ee3fc27eded75d3f4111f64d0951b0e7;hpb=9115776479fc67fe12cc3f7ccb8da2fd684d2232;p=apitrace diff --git a/wrappers/trace.py b/wrappers/trace.py index 3066836..4563f45 100644 --- a/wrappers/trace.py +++ b/wrappers/trace.py @@ -39,6 +39,45 @@ def getWrapperInterfaceName(interface): return "Wrap" + interface.expr + +class ExpanderMixin: + '''Mixin class that provides a bunch of methods to expand C expressions + from the specifications.''' + + __structs = None + __indices = None + + def expand(self, expr): + # Expand a C expression, replacing certain variables + if not isinstance(expr, basestring): + return expr + variables = {} + + if self.__structs is not None: + variables['self'] = '(%s)' % self.__structs[0] + if self.__indices is not None: + variables['i'] = self.__indices[0] + + expandedExpr = expr.format(**variables) + if expandedExpr != expr and 0: + sys.stderr.write(" %r -> %r\n" % (expr, expandedExpr)) + return expandedExpr + + def visitMember(self, structInstance, member_type, *args, **kwargs): + self.__structs = (structInstance, self.__structs) + try: + return self.visit(member_type, *args, **kwargs) + finally: + _, self.__structs = self.__structs + + def visitElement(self, element_index, element_type, *args, **kwargs): + self.__indices = (element_index, self.__indices) + try: + return self.visit(element_type, *args, **kwargs) + finally: + _, self.__indices = self.__indices + + class ComplexValueSerializer(stdapi.OnceVisitor): '''Type visitors which generates serialization functions for complex types. @@ -63,21 +102,13 @@ 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 '}' + print ' "%s",' % (name,) + print '};' + print 'static const trace::StructSig _struct%s_sig = {' % (struct.tag,) + print ' %u, "%s", %u, _struct%s_members' % (struct.id, struct.name, len(struct.members), struct.tag) + print '};' print def visitArray(self, array): @@ -150,7 +181,7 @@ class ComplexValueSerializer(stdapi.OnceVisitor): print -class ValueSerializer(stdapi.Visitor): +class ValueSerializer(stdapi.Visitor, ExpanderMixin): '''Visitor which generates code to serialize any type. Simple types are serialized inline here, whereas the serialization of @@ -158,6 +189,11 @@ class ValueSerializer(stdapi.Visitor): ComplexValueSerializer visitor above. ''' + def __init__(self): + #stdapi.Visitor.__init__(self) + self.indices = [] + self.instances = [] + def visitLiteral(self, literal, instance): print ' trace::localWriter.write%s(%s);' % (literal.kind, instance) @@ -181,17 +217,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 type, name in struct.members: + self.visitMember(instance, type, '(%s).%s' % (instance, name,)) + 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 +240,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) @@ -272,7 +312,7 @@ class WrapDecider(stdapi.Traverser): self.needsWrapping = True -class ValueWrapper(stdapi.Traverser): +class ValueWrapper(stdapi.Traverser, ExpanderMixin): '''Type visitor which will generate the code to wrap an instance. Wrapping is necessary mostly for interfaces, however interface pointers can @@ -281,12 +321,13 @@ class ValueWrapper(stdapi.Traverser): def visitStruct(self, struct, instance): for type, name in struct.members: - self.visit(type, "(%s).%s" % (instance, name)) + self.visitMember(instance, type, "(%s).%s" % (instance, name)) 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 +340,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 +363,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]")