]> git.cworth.org Git - apitrace/blobdiff - retrace.py
Don't abuse NotImplementedError.
[apitrace] / retrace.py
index 3b68d6018eee0ac19e4ce6138e8d198dff9ed9a4..9e9af208f53186d3fe6054406b4f3aad6d99d8e0 100644 (file)
 
 """Generic retracing code generator."""
 
 
 """Generic retracing code generator."""
 
-import stdapi
-import glapi
-from codegen import *
 
 
+import sys
 
 
-class ConstRemover(stdapi.Rebuilder):
+import specs.stdapi as stdapi
+import specs.glapi as glapi
 
 
-    def visit_const(self, const):
+
+class UnsupportedType(Exception):
+    pass
+
+
+class MutableRebuilder(stdapi.Rebuilder):
+    '''Type visitor which derives a mutable type.'''
+
+    def visitConst(self, const):
+        # Strip out const qualifier
         return const.type
 
         return const.type
 
-    def visit_opaque(self, opaque):
-        return opaque
+    def visitAlias(self, alias):
+        # Tear the alias on type changes
+        type = self.visit(alias.type)
+        if type is alias.type:
+            return alias
+        return type
 
 
+    def visitReference(self, reference):
+        # Strip out references
+        return reference.type
 
 
-def handle_entry(handle, value):
+
+def lookupHandle(handle, value):
     if handle.key is None:
         return "__%s_map[%s]" % (handle.name, value)
     else:
     if handle.key is None:
         return "__%s_map[%s]" % (handle.name, value)
     else:
@@ -48,124 +64,230 @@ def handle_entry(handle, value):
         return "__%s_map[%s][%s]" % (handle.name, key_name, value)
 
 
         return "__%s_map[%s][%s]" % (handle.name, key_name, value)
 
 
-class ValueExtractor(stdapi.Visitor):
+class ValueAllocator(stdapi.Visitor):
+
+    def visitLiteral(self, literal, lvalue, rvalue):
+        pass
+
+    def visitConst(self, const, lvalue, rvalue):
+        self.visit(const.type, lvalue, rvalue)
+
+    def visitAlias(self, alias, lvalue, rvalue):
+        self.visit(alias.type, lvalue, rvalue)
+
+    def visitEnum(self, enum, lvalue, rvalue):
+        pass
+
+    def visitBitmask(self, bitmask, lvalue, rvalue):
+        pass
+
+    def visitArray(self, array, lvalue, rvalue):
+        print '    %s = _allocator.alloc<%s>(&%s);' % (lvalue, array.type, rvalue)
+
+    def visitPointer(self, pointer, lvalue, rvalue):
+        print '    %s = _allocator.alloc<%s>(&%s);' % (lvalue, pointer.type, rvalue)
+
+    def visitIntPointer(self, pointer, lvalue, rvalue):
+        pass
+
+    def visitObjPointer(self, pointer, lvalue, rvalue):
+        pass
+
+    def visitLinearPointer(self, pointer, lvalue, rvalue):
+        pass
+
+    def visitReference(self, reference, lvalue, rvalue):
+        self.visit(reference.type, lvalue, rvalue);
+
+    def visitHandle(self, handle, lvalue, rvalue):
+        pass
+
+    def visitBlob(self, blob, lvalue, rvalue):
+        pass
+
+    def visitString(self, string, lvalue, rvalue):
+        pass
+
+    def visitStruct(self, struct, lvalue, rvalue):
+        pass
 
 
-    def visit_literal(self, literal, lvalue, rvalue):
-        #if literal.format in ('Bool', 'UInt'):
-        print '    %s = (%s).to%s();' % (lvalue, rvalue, literal.format)
+    def visitPolymorphic(self, polymorphic, lvalue, rvalue):
+        self.visit(polymorphic.defaultType, lvalue, rvalue)
 
 
-    def visit_const(self, const, lvalue, rvalue):
+    def visitOpaque(self, opaque, lvalue, rvalue):
+        pass
+
+
+class ValueDeserializer(stdapi.Visitor):
+
+    def visitLiteral(self, literal, lvalue, rvalue):
+        print '    %s = (%s).to%s();' % (lvalue, rvalue, literal.kind)
+
+    def visitConst(self, const, lvalue, rvalue):
         self.visit(const.type, lvalue, rvalue)
 
         self.visit(const.type, lvalue, rvalue)
 
-    def visit_alias(self, alias, lvalue, rvalue):
+    def visitAlias(self, alias, lvalue, rvalue):
         self.visit(alias.type, lvalue, rvalue)
     
         self.visit(alias.type, lvalue, rvalue)
     
-    def visit_enum(self, enum, lvalue, rvalue):
-        print '    %s = (%s).toSInt();' % (lvalue, rvalue)
+    def visitEnum(self, enum, lvalue, rvalue):
+        print '    %s = static_cast<%s>((%s).toSInt());' % (lvalue, enum, rvalue)
 
 
-    def visit_bitmask(self, bitmask, lvalue, rvalue):
+    def visitBitmask(self, bitmask, lvalue, rvalue):
         self.visit(bitmask.type, lvalue, rvalue)
 
         self.visit(bitmask.type, lvalue, rvalue)
 
-    def visit_array(self, array, lvalue, rvalue):
-        print '    const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (array.id, rvalue)
-        print '    if (__a%s) {' % (array.id)
-        length = '__a%s->values.size()' % array.id
-        print '        %s = new %s[%s];' % (lvalue, array.type, length)
-        index = '__j' + array.id
+    def visitArray(self, array, lvalue, rvalue):
+
+        tmp = '__a_' + array.tag + '_' + str(self.seq)
+        self.seq += 1
+
+        print '    if (%s) {' % (lvalue,)
+        print '        const trace::Array *%s = dynamic_cast<const trace::Array *>(&%s);' % (tmp, rvalue)
+        length = '%s->values.size()' % (tmp,)
+        index = '__j' + array.tag
         print '        for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
         try:
         print '        for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
         try:
-            self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.id, index))
+            self.visit(array.type, '%s[%s]' % (lvalue, index), '*%s->values[%s]' % (tmp, index))
         finally:
             print '        }'
         finally:
             print '        }'
-            print '    } else {'
-            print '        %s = NULL;' % lvalue
             print '    }'
     
             print '    }'
     
-    def visit_pointer(self, pointer, lvalue, rvalue):
-        print '    const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (pointer.id, rvalue)
-        print '    if (__a%s) {' % (pointer.id)
-        print '        %s = new %s;' % (lvalue, pointer.type)
+    def visitPointer(self, pointer, lvalue, rvalue):
+        tmp = '__a_' + pointer.tag + '_' + str(self.seq)
+        self.seq += 1
+
+        print '    if (%s) {' % (lvalue,)
+        print '        const trace::Array *%s = dynamic_cast<const trace::Array *>(&%s);' % (tmp, rvalue)
         try:
         try:
-            self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.id,))
+            self.visit(pointer.type, '%s[0]' % (lvalue,), '*%s->values[0]' % (tmp,))
         finally:
         finally:
-            print '    } else {'
-            print '        %s = NULL;' % lvalue
             print '    }'
 
             print '    }'
 
-    def visit_handle(self, handle, lvalue, rvalue):
-        OpaqueValueExtractor().visit(handle.type, lvalue, rvalue);
-        new_lvalue = handle_entry(handle, lvalue)
+    def visitIntPointer(self, pointer, lvalue, rvalue):
+        print '    %s = static_cast<%s>((%s).toPointer());' % (lvalue, pointer, rvalue)
+
+    def visitObjPointer(self, pointer, lvalue, rvalue):
+        old_lvalue = '(%s).toUIntPtr()' % (rvalue,)
+        new_lvalue = '_obj_map[%s]' % (old_lvalue,)
+        print '    if (retrace::verbosity >= 2) {'
+        print '        std::cout << std::hex << "obj 0x" << size_t(%s) << " <- 0x" << size_t(%s) << std::dec <<"\\n";' % (old_lvalue, new_lvalue)
+        print '    }'
+        print '    %s = static_cast<%s>(%s);' % (lvalue, pointer, new_lvalue)
+
+    def visitLinearPointer(self, pointer, lvalue, rvalue):
+        print '    %s = static_cast<%s>(retrace::toPointer(%s));' % (lvalue, pointer, rvalue)
+
+    def visitReference(self, reference, lvalue, rvalue):
+        self.visit(reference.type, lvalue, rvalue);
+
+    def visitHandle(self, handle, lvalue, rvalue):
+        #OpaqueValueDeserializer().visit(handle.type, lvalue, rvalue);
+        self.visit(handle.type, lvalue, rvalue);
+        new_lvalue = lookupHandle(handle, lvalue)
         print '    if (retrace::verbosity >= 2) {'
         print '        std::cout << "%s " << size_t(%s) << " <- " << size_t(%s) << "\\n";' % (handle.name, lvalue, new_lvalue)
         print '    }'
         print '    %s = %s;' % (lvalue, new_lvalue)
     
         print '    if (retrace::verbosity >= 2) {'
         print '        std::cout << "%s " << size_t(%s) << " <- " << size_t(%s) << "\\n";' % (handle.name, lvalue, new_lvalue)
         print '    }'
         print '    %s = %s;' % (lvalue, new_lvalue)
     
-    def visit_blob(self, blob, lvalue, rvalue):
+    def visitBlob(self, blob, lvalue, rvalue):
         print '    %s = static_cast<%s>((%s).toPointer());' % (lvalue, blob, rvalue)
     
         print '    %s = static_cast<%s>((%s).toPointer());' % (lvalue, blob, rvalue)
     
-    def visit_string(self, string, lvalue, rvalue):
+    def visitString(self, string, lvalue, rvalue):
         print '    %s = (%s)((%s).toString());' % (lvalue, string.expr, rvalue)
 
         print '    %s = (%s)((%s).toString());' % (lvalue, string.expr, rvalue)
 
+    seq = 0
+
+    def visitStruct(self, struct, lvalue, rvalue):
+        tmp = '__s_' + struct.tag + '_' + str(self.seq)
+        self.seq += 1
+
+        print '    const trace::Struct *%s = dynamic_cast<const trace::Struct *>(&%s);' % (tmp, rvalue)
+        print '    assert(%s);' % (tmp)
+        for i in range(len(struct.members)):
+            member_type, member_name = struct.members[i]
+            self.visit(member_type, '%s.%s' % (lvalue, member_name), '*%s->members[%s]' % (tmp, i))
+
+    def visitPolymorphic(self, polymorphic, lvalue, rvalue):
+        self.visit(polymorphic.defaultType, lvalue, rvalue)
+    
+    def visitOpaque(self, opaque, lvalue, rvalue):
+        raise UnsupportedType
+
 
 
-class OpaqueValueExtractor(ValueExtractor):
+class OpaqueValueDeserializer(ValueDeserializer):
     '''Value extractor that also understands opaque values.
 
     Normally opaque values can't be retraced, unless they are being extracted
     in the context of handles.'''
 
     '''Value extractor that also understands opaque values.
 
     Normally opaque values can't be retraced, unless they are being extracted
     in the context of handles.'''
 
-    def visit_opaque(self, opaque, lvalue, rvalue):
-        print '    %s = static_cast<%s>((%s).toPointer());' % (lvalue, opaque, rvalue)
+    def visitOpaque(self, opaque, lvalue, rvalue):
+        print '    %s = static_cast<%s>(retrace::toPointer(%s));' % (lvalue, opaque, rvalue)
 
 
 
 
-class ValueWrapper(stdapi.Visitor):
+class SwizzledValueRegistrator(stdapi.Visitor):
+    '''Type visitor which will register (un)swizzled value pairs, to later be
+    swizzled.'''
 
 
-    def visit_literal(self, literal, lvalue, rvalue):
+    def visitLiteral(self, literal, lvalue, rvalue):
         pass
 
         pass
 
-    def visit_alias(self, alias, lvalue, rvalue):
+    def visitAlias(self, alias, lvalue, rvalue):
         self.visit(alias.type, lvalue, rvalue)
     
         self.visit(alias.type, lvalue, rvalue)
     
-    def visit_enum(self, enum, lvalue, rvalue):
+    def visitEnum(self, enum, lvalue, rvalue):
         pass
 
         pass
 
-    def visit_bitmask(self, bitmask, lvalue, rvalue):
+    def visitBitmask(self, bitmask, lvalue, rvalue):
         pass
 
         pass
 
-    def visit_array(self, array, lvalue, rvalue):
-        print '    const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (array.id, rvalue)
-        print '    if (__a%s) {' % (array.id)
-        length = '__a%s->values.size()' % array.id
-        index = '__j' + array.id
+    def visitArray(self, array, lvalue, rvalue):
+        print '    const trace::Array *__a%s = dynamic_cast<const trace::Array *>(&%s);' % (array.tag, rvalue)
+        print '    if (__a%s) {' % (array.tag)
+        length = '__a%s->values.size()' % array.tag
+        index = '__j' + array.tag
         print '        for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
         try:
         print '        for (size_t {i} = 0; {i} < {length}; ++{i}) {{'.format(i = index, length = length)
         try:
-            self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.id, index))
+            self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.tag, index))
         finally:
             print '        }'
             print '    }'
     
         finally:
             print '        }'
             print '    }'
     
-    def visit_pointer(self, pointer, lvalue, rvalue):
-        print '    const Trace::Array *__a%s = dynamic_cast<const Trace::Array *>(&%s);' % (pointer.id, rvalue)
-        print '    if (__a%s) {' % (pointer.id)
+    def visitPointer(self, pointer, lvalue, rvalue):
+        print '    const trace::Array *__a%s = dynamic_cast<const trace::Array *>(&%s);' % (pointer.tag, rvalue)
+        print '    if (__a%s) {' % (pointer.tag)
         try:
         try:
-            self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.id,))
+            self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.tag,))
         finally:
             print '    }'
     
         finally:
             print '    }'
     
-    def visit_handle(self, handle, lvalue, rvalue):
+    def visitIntPointer(self, pointer, lvalue, rvalue):
+        pass
+    
+    def visitObjPointer(self, pointer, lvalue, rvalue):
+        print r'    _obj_map[(%s).toUIntPtr()] = %s;' % (rvalue, lvalue)
+    
+    def visitLinearPointer(self, pointer, lvalue, rvalue):
+        assert pointer.size is not None
+        if pointer.size is not None:
+            print r'    retrace::addRegion((%s).toUIntPtr(), %s, %s);' % (rvalue, lvalue, pointer.size)
+
+    def visitReference(self, reference, lvalue, rvalue):
+        pass
+    
+    def visitHandle(self, handle, lvalue, rvalue):
         print '    %s __orig_result;' % handle.type
         print '    %s __orig_result;' % handle.type
-        OpaqueValueExtractor().visit(handle.type, '__orig_result', rvalue);
+        OpaqueValueDeserializer().visit(handle.type, '__orig_result', rvalue);
         if handle.range is None:
             rvalue = "__orig_result"
         if handle.range is None:
             rvalue = "__orig_result"
-            entry = handle_entry(handle, rvalue) 
+            entry = lookupHandle(handle, rvalue) 
             print "    %s = %s;" % (entry, lvalue)
             print '    if (retrace::verbosity >= 2) {'
             print '        std::cout << "{handle.name} " << {rvalue} << " -> " << {lvalue} << "\\n";'.format(**locals())
             print '    }'
         else:
             print "    %s = %s;" % (entry, lvalue)
             print '    if (retrace::verbosity >= 2) {'
             print '        std::cout << "{handle.name} " << {rvalue} << " -> " << {lvalue} << "\\n";'.format(**locals())
             print '    }'
         else:
-            i = '__h' + handle.id
+            i = '__h' + handle.tag
             lvalue = "%s + %s" % (lvalue, i)
             rvalue = "__orig_result + %s" % (i,)
             lvalue = "%s + %s" % (lvalue, i)
             rvalue = "__orig_result + %s" % (i,)
-            entry = handle_entry(handle, rvalue) 
+            entry = lookupHandle(handle, rvalue) 
             print '    for ({handle.type} {i} = 0; {i} < {handle.range}; ++{i}) {{'.format(**locals())
             print '        {entry} = {lvalue};'.format(**locals())
             print '        if (retrace::verbosity >= 2) {'
             print '    for ({handle.type} {i} = 0; {i} < {handle.range}; ++{i}) {{'.format(**locals())
             print '        {entry} = {lvalue};'.format(**locals())
             print '        if (retrace::verbosity >= 2) {'
@@ -173,70 +295,140 @@ class ValueWrapper(stdapi.Visitor):
             print '        }'
             print '    }'
     
             print '        }'
             print '    }'
     
-    def visit_blob(self, blob, lvalue, rvalue):
+    def visitBlob(self, blob, lvalue, rvalue):
         pass
     
         pass
     
-    def visit_string(self, string, lvalue, rvalue):
+    def visitString(self, string, lvalue, rvalue):
+        pass
+
+    seq = 0
+
+    def visitStruct(self, struct, lvalue, rvalue):
+        tmp = '__s_' + struct.tag + '_' + str(self.seq)
+        self.seq += 1
+
+        print '    const trace::Struct *%s = dynamic_cast<const trace::Struct *>(&%s);' % (tmp, rvalue)
+        print '    assert(%s);' % (tmp,)
+        print '    (void)%s;' % (tmp,)
+        for i in range(len(struct.members)):
+            member_type, member_name = struct.members[i]
+            self.visit(member_type, '%s.%s' % (lvalue, member_name), '*%s->members[%s]' % (tmp, i))
+    
+    def visitPolymorphic(self, polymorphic, lvalue, rvalue):
+        self.visit(polymorphic.defaultType, lvalue, rvalue)
+    
+    def visitOpaque(self, opaque, lvalue, rvalue):
         pass
 
 
 class Retracer:
 
         pass
 
 
 class Retracer:
 
-    def retrace_function(self, function):
-        print 'static void retrace_%s(Trace::Call &call) {' % function.name
-        self.retrace_function_body(function)
+    def retraceFunction(self, function):
+        print 'static void retrace_%s(trace::Call &call) {' % function.name
+        self.retraceFunctionBody(function)
         print '}'
         print
 
         print '}'
         print
 
-    def retrace_function_body(self, function):
-        if not function.sideeffects:
-            print '    (void)call;'
-            return
+    def retraceInterfaceMethod(self, interface, method):
+        print 'static void retrace_%s__%s(trace::Call &call) {' % (interface.name, method.name)
+        self.retraceInterfaceMethodBody(interface, method)
+        print '}'
+        print
+
+    def retraceFunctionBody(self, function):
+        assert function.sideeffects
+
+        self.deserializeArgs(function)
+        
+        self.invokeFunction(function)
+
+        self.swizzleValues(function)
+
+    def retraceInterfaceMethodBody(self, interface, method):
+        assert method.sideeffects
 
 
+        self.deserializeThisPointer(interface)
+
+        self.deserializeArgs(method)
+        
+        self.invokeInterfaceMethod(interface, method)
+
+        self.swizzleValues(method)
+
+    def deserializeThisPointer(self, interface):
+        print r'    %s *_this;' % (interface.name,)
+        print r'    _this = static_cast<%s *>(_obj_map[call.arg(0).toUIntPtr()]);' % (interface.name,)
+        print r'    if (!_this) {'
+        print r'        retrace::warning(call) << "NULL this pointer\n";'
+        print r'        return;'
+        print r'    }'
+
+    def deserializeArgs(self, function):
+        print '    retrace::ScopedAllocator _allocator;'
+        print '    (void)_allocator;'
         success = True
         for arg in function.args:
         success = True
         for arg in function.args:
-            arg_type = ConstRemover().visit(arg.type)
-            #print '    // %s ->  %s' % (arg.type, arg_type)
+            arg_type = MutableRebuilder().visit(arg.type)
             print '    %s %s;' % (arg_type, arg.name)
             rvalue = 'call.arg(%u)' % (arg.index,)
             lvalue = arg.name
             try:
             print '    %s %s;' % (arg_type, arg.name)
             rvalue = 'call.arg(%u)' % (arg.index,)
             lvalue = arg.name
             try:
-                self.extract_arg(function, arg, arg_type, lvalue, rvalue)
-            except NotImplementedError:
-                success = False
-                print '    %s = 0; // FIXME' % arg.name
+                self.extractArg(function, arg, arg_type, lvalue, rvalue)
+            except UnsupportedType:
+                success =  False
+                print '    memset(&%s, 0, sizeof %s); // FIXME' % (arg.name, arg.name)
+            print
+
         if not success:
             print '    if (1) {'
         if not success:
             print '    if (1) {'
-            self.fail_function(function)
+            self.failFunction(function)
+            if function.name[-1].islower():
+                sys.stderr.write('warning: unsupported %s call\n' % function.name)
             print '    }'
             print '    }'
-        self.call_function(function)
+
+    def swizzleValues(self, function):
         for arg in function.args:
             if arg.output:
         for arg in function.args:
             if arg.output:
-                arg_type = ConstRemover().visit(arg.type)
+                arg_type = MutableRebuilder().visit(arg.type)
                 rvalue = 'call.arg(%u)' % (arg.index,)
                 lvalue = arg.name
                 try:
                 rvalue = 'call.arg(%u)' % (arg.index,)
                 lvalue = arg.name
                 try:
-                    ValueWrapper().visit(arg_type, lvalue, rvalue)
-                except NotImplementedError:
-                    print '   // FIXME: %s' % arg.name
+                    self.regiterSwizzledValue(arg_type, lvalue, rvalue)
+                except UnsupportedType:
+                    print '    // XXX: %s' % arg.name
         if function.type is not stdapi.Void:
             rvalue = '*call.ret'
             lvalue = '__result'
             try:
         if function.type is not stdapi.Void:
             rvalue = '*call.ret'
             lvalue = '__result'
             try:
-                ValueWrapper().visit(function.type, lvalue, rvalue)
-            except NotImplementedError:
-                print '   // FIXME: result'
-
-    def fail_function(self, function):
-        print '    if (retrace::verbosity >= 0)'
-        print '        std::cerr << "warning: unsupported call %s\\n";' % function.name
+                self.regiterSwizzledValue(function.type, lvalue, rvalue)
+            except UnsupportedType:
+                raise
+                print '    // XXX: result'
+
+    def failFunction(self, function):
+        print '    if (retrace::verbosity >= 0) {'
+        print '        retrace::unsupported(call);'
+        print '    }'
         print '    return;'
 
         print '    return;'
 
-    def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
-        ValueExtractor().visit(arg_type, lvalue, rvalue)
+    def extractArg(self, function, arg, arg_type, lvalue, rvalue):
+        ValueAllocator().visit(arg_type, lvalue, rvalue)
+        if arg.input:
+            ValueDeserializer().visit(arg_type, lvalue, rvalue)
+    
+    def extractOpaqueArg(self, function, arg, arg_type, lvalue, rvalue):
+        try:
+            ValueAllocator().visit(arg_type, lvalue, rvalue)
+        except UnsupportedType:
+            pass
+        OpaqueValueDeserializer().visit(arg_type, lvalue, rvalue)
 
 
-    def call_function(self, function):
-        arg_names = ", ".join([arg.name for arg in function.args])
+    def regiterSwizzledValue(self, type, lvalue, rvalue):
+        visitor = SwizzledValueRegistrator()
+        visitor.visit(type, lvalue, rvalue)
+
+    def invokeFunction(self, function):
+        arg_names = ", ".join(function.argNames())
         if function.type is not stdapi.Void:
             print '    %s __result;' % (function.type)
             print '    __result = %s(%s);' % (function.name, arg_names)
         if function.type is not stdapi.Void:
             print '    %s __result;' % (function.type)
             print '    __result = %s(%s);' % (function.name, arg_names)
@@ -244,40 +436,28 @@ class Retracer:
         else:
             print '    %s(%s);' % (function.name, arg_names)
 
         else:
             print '    %s(%s);' % (function.name, arg_names)
 
-    def filter_function(self, function):
-        return True
-
-    def retrace_functions(self, functions):
-        functions = filter(self.filter_function, functions)
-
-        for function in functions:
-            self.retrace_function(function)
-
-        print 'void retrace::retrace_call(Trace::Call &call) {'
-        print '    const char *name = call.name().c_str();'
-        print
-
-        func_dict = dict([(function.name, function) for function in functions])
-
-        def handle_case(function_name):
-            function = func_dict[function_name]
-            print '        retrace_%s(call);' % function.name
-            print '        return;'
-    
-        string_switch('name', func_dict.keys(), handle_case)
+    def invokeInterfaceMethod(self, interface, method):
+        arg_names = ", ".join(method.argNames())
+        if method.type is not stdapi.Void:
+            print '    %s __result;' % (method.type)
+            print '    __result = _this->%s(%s);' % (method.name, arg_names)
+            print '    (void)__result;'
+        else:
+            print '    _this->%s(%s);' % (method.name, arg_names)
 
 
-        print '    retrace_unknown(call);'
-        print '}'
-        print
+    def filterFunction(self, function):
+        return True
 
 
+    table_name = 'retrace::callbacks'
 
 
-    def retrace_api(self, api):
+    def retraceApi(self, api):
 
 
+        print '#include "os_time.hpp"'
         print '#include "trace_parser.hpp"'
         print '#include "retrace.hpp"'
         print
 
         print '#include "trace_parser.hpp"'
         print '#include "retrace.hpp"'
         print
 
-        types = api.all_types()
+        types = api.getAllTypes()
         handles = [type for type in types if isinstance(type, stdapi.Handle)]
         handle_names = set()
         for handle in handles:
         handles = [type for type in types if isinstance(type, stdapi.Handle)]
         handle_names = set()
         for handle in handles:
@@ -290,5 +470,32 @@ class Retracer:
                 handle_names.add(handle.name)
         print
 
                 handle_names.add(handle.name)
         print
 
-        self.retrace_functions(api.functions)
+        print 'static std::map<unsigned long long, void *> _obj_map;'
+        print
+
+        functions = filter(self.filterFunction, api.functions)
+        for function in functions:
+            if function.sideeffects:
+                self.retraceFunction(function)
+        interfaces = api.getAllInterfaces()
+        for interface in interfaces:
+            for method in interface.iterMethods():
+                if method.sideeffects:
+                    self.retraceInterfaceMethod(interface, method)
+
+        print 'const retrace::Entry %s[] = {' % self.table_name
+        for function in functions:
+            if function.sideeffects:
+                print '    {"%s", &retrace_%s},' % (function.name, function.name)
+            else:
+                print '    {"%s", &retrace::ignore},' % (function.name,)
+        for interface in interfaces:
+            for method in interface.iterMethods():                
+                if method.sideeffects:
+                    print '    {"%s::%s", &retrace_%s__%s},' % (interface.name, method.name, interface.name, method.name)
+                else:
+                    print '    {"%s::%s", &retrace::ignore},' % (interface.name, method.name)
+        print '    {NULL, NULL}'
+        print '};'
+        print