]> git.cworth.org Git - apitrace/commitdiff
Merge branch 'd3dretrace'
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Fri, 13 Apr 2012 16:36:19 +0000 (17:36 +0100)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Fri, 13 Apr 2012 16:36:19 +0000 (17:36 +0100)
1  2 
CMakeLists.txt
glretrace.py
retrace.hpp
retrace.py
trace.py

diff --combined CMakeLists.txt
index 28c86d372dfaf108f64110251bc5fc6808777035,9ced8e365a4ac6e2c5200f9c27ff3c92240bbc43..265b2141159e0e4ed66c35f98242f29adc5c0561
@@@ -376,7 -376,7 +376,7 @@@ if (WIN32
          add_custom_command (
              OUTPUT d3d10trace.cpp
              COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d10trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d10trace.cpp
 -            DEPENDS d3d10trace.py trace.py specs/d3d10misc.py specs/d3d10.py specs/dxgi.py specs/dxgitype.py specs/dxgiformat.py specs/winapi.py specs/stdapi.py
 +            DEPENDS d3d10trace.py trace.py specs/d3d10misc.py specs/d3d10.py specs/d3d10sdklayers.py specs/dxgi.py specs/dxgitype.py specs/dxgiformat.py specs/winapi.py specs/stdapi.py
          )
          add_library (d3d10 MODULE specs/d3d10.def d3d10trace.cpp)
          target_link_libraries (d3d10
          install (TARGETS d3d10 LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
      endif (DirectX_D3D10_INCLUDE_DIR)
  
 +    # d3d10_1.dll
 +    if (DirectX_D3D10_INCLUDE_DIR)
 +        include_directories (SYSTEM ${DirectX_D3D10_INCLUDE_DIR})
 +        add_custom_command (
 +            OUTPUT d3d10_1trace.cpp
 +            COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3d10_1trace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3d10_1trace.cpp
 +            DEPENDS d3d10_1trace.py trace.py specs/d3d10_1.py specs/d3d10.py specs/d3d10sdklayers.py specs/dxgi.py specs/dxgitype.py specs/dxgiformat.py specs/winapi.py specs/stdapi.py
 +        )
 +        add_library (d3d10_1 MODULE specs/d3d10_1.def d3d10_1trace.cpp)
 +        target_link_libraries (d3d10_1
 +            common
 +            ${ZLIB_LIBRARIES}
 +            ${SNAPPY_LIBRARIES}
 +        )
 +        set_target_properties (d3d10_1
 +            PROPERTIES PREFIX ""
 +            RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers
 +            LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers
 +        )
 +        install (TARGETS d3d10_1 LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
 +    endif (DirectX_D3D10_INCLUDE_DIR)
 +
      # opengl32.dll
      add_custom_command (
          OUTPUT wgltrace.cpp
@@@ -671,6 -649,28 +671,28 @@@ if (ENABLE_EGL AND X11_FOUND AND NOT WI
      install (TARGETS eglretrace RUNTIME DESTINATION bin) 
  endif ()
  
+ if (WIN32 AND DirectX_D3DX9_FOUND)
+     add_custom_command (
+         OUTPUT d3dretrace_d3d9.cpp
+         COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/d3dretrace.py > ${CMAKE_CURRENT_BINARY_DIR}/d3dretrace_d3d9.cpp
+         DEPENDS d3dretrace.py retrace.py specs/d3d9.py specs/d3d9types.py specs/d3d9caps.py specs/winapi.py specs/stdapi.py
+     )
+     include_directories (SYSTEM ${DirectX_D3DX9_INCLUDE_DIR})
+     add_executable (d3dretrace
+         retrace.cpp
+         retrace_stdc.cpp
+         d3dretrace_main.cpp
+         d3dretrace_d3d9.cpp
+     )
+     target_link_libraries (d3dretrace
+         common
+         ${ZLIB_LIBRARIES}
+         ${SNAPPY_LIBRARIES}
+         ${DirectX_D3D9_LIBRARY}
+     )
+ endif ()
  ##############################################################################
  # CLI
  
diff --combined glretrace.py
index cd7fe803267766954d6fd4e8450d9761c834ceb4,56741467075171bd33618491b6cfed385c1f74a5..d91c8a25fe2ec2e68d39c89c15a2ada41e1b5f90
@@@ -178,7 -178,7 +178,7 @@@ class GlRetracer(Retracer)
          is_misc_draw = function.name in self.misc_draw_function_names
  
          if is_array_pointer or is_draw_array or is_draw_elements:
-             print '    if (glretrace::parser.version < 1) {'
+             print '    if (retrace::parser.version < 1) {'
  
              if is_array_pointer or is_draw_array:
                  print '        GLint __array_buffer = 0;'
          # Handle pointer with offsets into the current pack pixel buffer
          # object.
          if function.name in self.pack_function_names and arg.output:
-             self.extractOpaqueArg(function, arg, arg_type, lvalue, rvalue)
+             assert isinstance(arg_type, (stdapi.Pointer, stdapi.Array, stdapi.Blob, stdapi.Opaque))
+             print '    %s = static_cast<%s>((%s).toPointer());' % (lvalue, arg_type, rvalue)
              return
  
          if arg.type is glapi.GLlocation \
              print '        samples = max_samples;'
              print '    }'
  
 +        # These parameters are referred beyond the call life-time
 +        # TODO: Replace ad-hoc solution for bindable parameters with general one
 +        if function.name in ('glFeedbackBuffer', 'glSelectBuffer') and arg.output:
 +            print '    _allocator.bind(%s);' % arg.name
 +
 +
  
  if __name__ == '__main__':
      print r'''
diff --combined retrace.hpp
index 8ce15ad6720c7e0696440fd5688da523d90452bc,7357a703669e4d06a69eaed7f2b292b8345ecc88..c1e556a97fbb03d726be09de3cb92540de88e5fc
  #ifndef _RETRACE_HPP_
  #define _RETRACE_HPP_
  
 +#include <assert.h>
  #include <string.h>
 +#include <stdint.h>
  
  #include <list>
  #include <map>
  #include <ostream>
  
  #include "trace_model.hpp"
+ #include "trace_parser.hpp"
  
  
  namespace retrace {
  
  
+ extern trace::Parser parser;
  /**
   * Handle map.
   *
@@@ -88,11 -90,11 +92,11 @@@ public
  class ScopedAllocator
  {
  private:
 -    void *next;
 +    uintptr_t next;
  
  public:
      ScopedAllocator() :
 -        next(NULL) {
 +        next(0) {
      }
  
      inline void *
              return NULL;
          }
  
 -        void * * buf = static_cast<void **>(malloc(sizeof(void *) + size));
 +        uintptr_t * buf = static_cast<uintptr_t *>(malloc(sizeof(uintptr_t) + size));
          if (!buf) {
              return NULL;
          }
  
          *buf = next;
 -        next = buf;
 +        next = reinterpret_cast<uintptr_t>(buf);
 +        assert((next & 1) == 0);
  
 -        return &buf[1];
 +        return static_cast<void *>(&buf[1]);
      }
  
      template< class T >
          return static_cast<T *>(alloc(sizeof(T) * n));
      }
  
+     /**
+      * Allocate an array with the same dimensions as the specified value.
+      */
+     template< class T >
+     inline T *
+     alloc(const trace::Value *value) {
+         const trace::Array *array = dynamic_cast<const trace::Array *>(value);
+         if (array) {
+             return alloc<T>(array->size());
+         }
+         const trace::Null *null = dynamic_cast<const trace::Null *>(value);
+         if (null) {
+             return NULL;
+         }
+         assert(0);
+         return NULL;
+     }
 +    /**
 +     * Prevent this pointer from being automatically freed.
 +     */
 +    template< class T >
 +    inline void
 +    bind(T *ptr) {
 +        if (ptr) {
 +            reinterpret_cast<uintptr_t *>(ptr)[-1] |= 1;
 +        }
 +    }
 +
      inline
      ~ScopedAllocator() {
          while (next) {
 -            void *temp = *static_cast<void **>(next);
 -            free(next);
 +            uintptr_t temp = *reinterpret_cast<uintptr_t *>(next);
 +
 +            bool bind = temp & 1;
 +            temp &= ~1;
 +
 +            if (!bind) {
 +                free(reinterpret_cast<void *>(next));
 +            }
 +
              next = temp;
          }
      }
diff --combined retrace.py
index e4d462ae99ed5bdabc8ecc8a473a21dfe53db05e,ee85f29d6d5de771e08b488ae0558a3e5d12a14f..a450f8221ea47499622b118896fa6ed0f6783720
@@@ -33,13 -33,26 +33,26 @@@ import specs.stdapi as stdap
  import specs.glapi as glapi
  
  
- class ConstRemover(stdapi.Rebuilder):
-     '''Type visitor which strips out const qualifiers from types.'''
+ class MutableRebuilder(stdapi.Rebuilder):
+     '''Type visitor which derives a mutable type.'''
  
      def visitConst(self, const):
+         # Strip out const qualifier
          return const.type
  
+     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 visitOpaque(self, opaque):
+         # Don't recursule
          return opaque
  
  
@@@ -51,6 -64,57 +64,57 @@@ def lookupHandle(handle, value)
          return "__%s_map[%s][%s]" % (handle.name, key_name, value)
  
  
+ 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 visitPolymorphic(self, polymorphic, lvalue, rvalue):
+         self.visit(polymorphic.defaultType, lvalue, rvalue)
  class ValueDeserializer(stdapi.Visitor):
  
      def visitLiteral(self, literal, lvalue, rvalue):
          self.visit(bitmask.type, lvalue, rvalue)
  
      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
-         print '        %s = _allocator.alloc<%s>(%s);' % (lvalue, array.type, length)
+         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:
-             self.visit(array.type, '%s[%s]' % (lvalue, index), '*__a%s->values[%s]' % (array.tag, index))
+             self.visit(array.type, '%s[%s]' % (lvalue, index), '*%s->values[%s]' % (tmp, index))
          finally:
              print '        }'
-             print '    } else {'
-             print '        %s = NULL;' % lvalue
              print '    }'
      
      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)
-         print '        %s = _allocator.alloc<%s>();' % (lvalue, pointer.type)
+         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:
-             self.visit(pointer.type, '%s[0]' % (lvalue,), '*__a%s->values[0]' % (pointer.tag,))
+             self.visit(pointer.type, '%s[0]' % (lvalue,), '*%s->values[0]' % (tmp,))
          finally:
-             print '    } else {'
-             print '        %s = NULL;' % lvalue
              print '    }'
  
      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);
      def visitString(self, string, lvalue, 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)
  
  class OpaqueValueDeserializer(ValueDeserializer):
      '''Value extractor that also understands opaque values.
@@@ -165,11 -256,17 +256,17 @@@ class SwizzledValueRegistrator(stdapi.V
      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
          OpaqueValueDeserializer().visit(handle.type, '__orig_result', 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)
  
  class Retracer:
  
          print '}'
          print
  
+     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):
 -        if not function.sideeffects:
 -            print '    (void)call;'
 -            return
 +        assert function.sideeffects
  
 -        if not method.sideeffects:
 -            print '    (void)call;'
 -            return
+         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:
-             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:
                  self.extractArg(function, arg, arg_type, lvalue, rvalue)
              except NotImplementedError:
-                 success = False
-                 print '    %s = 0; // FIXME' % arg.name
+                 success =  False
+                 print '    memset(&%s, 0, sizeof %s); // FIXME' % (arg.name, arg.name)
+             print
          if not success:
              print '    if (1) {'
              self.failFunction(function)
+             if function.name[-1].islower():
+                 sys.stderr.write('warning: unsupported %s call\n' % function.name)
              print '    }'
-         self.invokeFunction(function)
+     def swizzleValues(self, function):
          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:
              try:
                  self.regiterSwizzledValue(function.type, lvalue, rvalue)
              except NotImplementedError:
+                 raise
                  print '    // XXX: result'
-         if not success:
-             if function.name[-1].islower():
-                 sys.stderr.write('warning: unsupported %s call\n' % function.name)
  
      def failFunction(self, function):
          print '    if (retrace::verbosity >= 0) {'
          print '    return;'
  
      def extractArg(self, function, arg, arg_type, lvalue, rvalue):
-         ValueDeserializer().visit(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 NotImplementedError:
+             pass
          OpaqueValueDeserializer().visit(arg_type, lvalue, rvalue)
  
      def regiterSwizzledValue(self, type, lvalue, rvalue):
          else:
              print '    %s(%s);' % (function.name, arg_names)
  
+     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)
      def filterFunction(self, function):
          return True
  
      table_name = 'retrace::callbacks'
  
-     def retraceFunctions(self, functions):
-         functions = filter(self.filterFunction, functions)
-         for function in functions:
-             if function.sideeffects:
-                 self.retraceFunction(function)
-         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,)
-         print '    {NULL, NULL}'
-         print '};'
-         print
      def retraceApi(self, api):
  
          print '#include "os_time.hpp"'
                  handle_names.add(handle.name)
          print
  
-         self.retraceFunctions(api.functions)
+         print 'static std::map<unsigned long long, void *> _obj_map;'
+         print
+         functions = filter(self.filterFunction, api.functions)
+         for function in functions:
 -            self.retraceFunction(function)
++            if function.sideeffects:
++                self.retraceFunction(function)
+         interfaces = api.getAllInterfaces()
+         for interface in interfaces:
+             for method in interface.iterMethods():
 -                self.retraceInterfaceMethod(interface, method)
++                if method.sideeffects:
++                    self.retraceInterfaceMethod(interface, method)
+         print 'const retrace::Entry %s[] = {' % self.table_name
+         for function in functions:
 -            print '    {"%s", &retrace_%s},' % (function.name, function.name)
++            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():
 -                print '    {"%s::%s", &retrace_%s__%s},' % (interface.name, method.name, interface.name, method.name)
++            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
  
diff --combined trace.py
index 397fa9d80c953e29eba05f772f129a47a3f65d1e,7350d932421e6572b1c4caae15fca059d408d7fb..4d6d97450501b12280740aecbd06b45a9d22979e
+++ b/trace.py
@@@ -108,12 -108,18 +108,18 @@@ class ComplexValueSerializer(stdapi.Onc
      def visitIntPointer(self, pointer):
          pass
  
+     def visitObjPointer(self, pointer):
+         self.visit(pointer.type)
      def visitLinearPointer(self, pointer):
          self.visit(pointer.type)
  
      def visitHandle(self, handle):
          self.visit(handle.type)
  
+     def visitReference(self, reference):
+         self.visit(reference.type)
      def visitAlias(self, alias):
          self.visit(alias.type)
  
@@@ -208,9 -214,15 +214,15 @@@ class ValueSerializer(stdapi.Visitor)
      def visitIntPointer(self, pointer, instance):
          print '    trace::localWriter.writeOpaque((const void *)%s);' % instance
  
+     def visitObjPointer(self, pointer, instance):
+         print '    trace::localWriter.writeOpaque((const void *)%s);' % instance
      def visitLinearPointer(self, pointer, instance):
          print '    trace::localWriter.writeOpaque((const void *)%s);' % instance
  
+     def visitReference(self, reference, instance):
+         self.visit(reference.type, instance)
      def visitHandle(self, handle, instance):
          self.visit(handle.type, instance)
  
@@@ -271,9 -283,17 +283,17 @@@ class ValueWrapper(stdapi.Visitor)
      def visitIntPointer(self, pointer, instance):
          pass
  
+     def visitObjPointer(self, pointer, instance):
+         print "    if (%s) {" % instance
+         self.visit(pointer.type, "*" + instance)
+         print "    }"
+     
      def visitLinearPointer(self, pointer, instance):
          pass
  
+     def visitReference(self, reference, instance):
+         self.visit(reference.type, instance)
+     
      def visitHandle(self, handle, instance):
          self.visit(handle.type, instance)
  
@@@ -523,7 -543,7 +543,7 @@@ class Tracer
                  self.wrapArg(method, arg)
                  if riid is not None and isinstance(arg.type, Pointer):
                      if isinstance(arg.type.type, Opaque):
 -                        self.wrapIid(riid, arg)
 +                        self.wrapIid(interface, method, riid, arg)
                      else:
                          assert isinstance(arg.type.type, Pointer)
                          assert isinstance(arg.type.type.type, Interface)
              print '    if (!__result)'
              print '        delete this;'
  
 -    def wrapIid(self, riid, out):
 +    def wrapIid(self, interface, method, riid, out):
              print '    if (%s && *%s) {' % (out.name, out.name)
              print '        if (*%s == m_pInstance) {' % (out.name,)
              print '            *%s = this;' % (out.name,)
                  print r'            *%s = new Wrap%s((%s *) *%s);' % (out.name, iface.name, iface.name, out.name)
                  print r'        }'
              print r'        else {'
 -            print r'            os::log("apitrace: warning: %s: 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",'
 -            print r'                    __FUNCTION__,'
 +            print r'            os::log("apitrace: warning: %s::%s: unknown IID {0x%08lX,0x%04X,0x%04X,{0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X}}\n",'
 +            print r'                    "%s", "%s",' % (interface.name, method.name)
              print r'                    %s.Data1, %s.Data2, %s.Data3,' % (riid.name, riid.name, riid.name)
              print r'                    %s.Data4[0],' % (riid.name,)
              print r'                    %s.Data4[1],' % (riid.name,)