[cfe-commits] [libcxxabi] r147898 - in /libcxxabi/trunk/src: private_typeinfo.cpp private_typeinfo.h

Howard Hinnant hhinnant at apple.com
Tue Jan 10 16:11:17 PST 2012


Author: hhinnant
Date: Tue Jan 10 18:11:17 2012
New Revision: 147898

URL: http://llvm.org/viewvc/llvm-project?rev=147898&view=rev
Log:
This is a transitory commit for __dynamic_cast.  It contains debugging statements that are not intended to be in the finished product.  However some of the dubbing statements themselves contain important documentation such as how to navigate a __class_type_info hierarchy, documenting object offset and inheritance access.  The intention is that this debugging code will migrate into both actual code and comments.  And capturing it here so that there is no chance this stuff will be lost.

Modified:
    libcxxabi/trunk/src/private_typeinfo.cpp
    libcxxabi/trunk/src/private_typeinfo.h

Modified: libcxxabi/trunk/src/private_typeinfo.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/private_typeinfo.cpp?rev=147898&r1=147897&r2=147898&view=diff
==============================================================================
--- libcxxabi/trunk/src/private_typeinfo.cpp (original)
+++ libcxxabi/trunk/src/private_typeinfo.cpp Tue Jan 10 18:11:17 2012
@@ -9,11 +9,26 @@
 
 #include "private_typeinfo.h"
 
+#include <iostream>
+
+namespace std
+{
+
+type_info::~type_info()
+{
+}
+
+}  // std
+
 namespace __cxxabiv1
 {
 
 // __fundamental_type_info
 
+// This miraculously (compiler magic) emits the type_info's for:
+//   1. all of the fundamental types
+//   2. pointers to all of the fundamental types
+//   3. pointers to all of the const fundamental types
 __fundamental_type_info::~__fundamental_type_info()
 {
 }
@@ -42,18 +57,60 @@
 {
 }
 
+void
+__class_type_info::display(const void* obj) const
+{
+    std::cout << "\n__class_type_info::this = " << obj << "  " << name() << '\n';
+}
+
 // __si_class_type_info
 
 __si_class_type_info::~__si_class_type_info()
 {
 }
 
+void
+__si_class_type_info::display(const void* obj) const
+{
+    std::cout << "\n__si_class_type_info::this = " << obj << "  " << name() << '\n';
+    __base_type->display(obj);
+}
+
 // __vmi_class_type_info
 
 __vmi_class_type_info::~__vmi_class_type_info()
 {
 }
 
+void
+__vmi_class_type_info::display(const void* obj) const
+{
+    std::cout << "\n__vmi_class_type_info::this = " << obj << "  " << name() << '\n';
+    if (__flags & __non_diamond_repeat_mask)
+        std::cout << "__non_diamond_repeat_mask\n";
+    if (__flags & __diamond_shaped_mask)
+        std::cout << "__diamond_shaped_mask\n";
+    std::cout << "__base_count = " << __base_count << '\n';
+    for (const __base_class_type_info* p = __base_info; p < __base_info + __base_count; ++p)
+        p->display(obj);
+}
+
+void
+__base_class_type_info::display(const void* obj) const
+{
+    if (__offset_flags & __virtual_mask)
+        std::cout << "__virtual_mask\n";
+    if (__offset_flags & __public_mask)
+        std::cout << "__public_mask\n";
+    ptrdiff_t offset_to_base = __offset_flags >> __offset_shift;
+    if (__offset_flags & __virtual_mask)
+    {
+        char* vtable = *(char**)obj;
+        offset_to_base = (ptrdiff_t)vtable[offset_to_base];
+    }
+    __base_type->display((char*)obj + offset_to_base);
+}
+
 // __pbase_type_info
 
 __pbase_type_info::~__pbase_type_info()
@@ -72,4 +129,53 @@
 {
 }
 
+// __dynamic_cast
+
+// static_ptr: source address to be adjusted; nonnull, and since the
+//   source object is polymorphic, *(void**)static_ptr is a virtual table pointer.
+// static_type: static type of the source object.
+// dst_type: destination type (the "T" in "dynamic_cast<T>(v)").
+// src2dst_offset: a static hint about the location of the
+//                 source subobject with respect to the complete object;
+//                 special negative values are:
+//                     -1: no hint
+//                     -2: static_type is not a public base of dst_type
+//                     -3: static_type is a multiple public base type but never a
+//                         virtual base type
+//                 otherwise, the static_type type is a unique public nonvirtual
+//                 base type of dst_type at offset src2dst_offset from the
+//                 origin of dst_type.
+// Returns either one of:
+//    1.  dynamic_ptr adjusted from static_ptr given a public path from
+//        (static_ptr, static_type) to dst_type without ambiguity, or
+//    2.  dynamic_ptr adjusted from static_ptr given a public path from
+//        (static_ptr, static_type) to (dynamic_ptr, dynamic_type) and also
+//        a public path from (dynamic_ptr, dynamic_type) to dst_type without
+//        ambiguity.
+// Things I think I know:
+//     This is a DAG rooted at dynamic_type and going up.
+//     Don't care about anything above static_type.
+//     There can be only one dynamic_type and it is at the root.
+//     A dst_type can never appear above another dst_type.
+extern "C"
+void*
+__dynamic_cast(const void* static_ptr,
+			   const __class_type_info* static_type,
+			   const __class_type_info* dst_type,
+			   std::ptrdiff_t src2dst_offset)
+{
+std::cout << "static_ptr = " << static_ptr << '\n';
+std::cout << "static_type = " << static_type << '\n';
+std::cout << "dst_type = " << dst_type << '\n';
+std::cout << "src2dst_offset = " << src2dst_offset << '\n';
+    void** vtable = *(void***)static_ptr;
+    ptrdiff_t offset_to_derived = (ptrdiff_t)vtable[-2];
+    const void* dynamic_ptr = (const char*)static_ptr + offset_to_derived;
+    const __class_type_info* dynamic_type = (const __class_type_info*)vtable[-1];
+std::cout << "dynamic_ptr = " << dynamic_ptr << '\n';
+std::cout << "dynamic_type = " << dynamic_type << '\n';
+dynamic_type->display(dynamic_ptr);
+    return 0;
+}
+
 }  // __cxxabiv1

Modified: libcxxabi/trunk/src/private_typeinfo.h
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/private_typeinfo.h?rev=147898&r1=147897&r2=147898&view=diff
==============================================================================
--- libcxxabi/trunk/src/private_typeinfo.h (original)
+++ libcxxabi/trunk/src/private_typeinfo.h Tue Jan 10 18:11:17 2012
@@ -43,13 +43,17 @@
     virtual ~__enum_type_info();
 };
 
+// Has no base class
 class __class_type_info
     : public std::type_info
 {
 public:
     virtual ~__class_type_info();
+
+    virtual void display(const void* obj) const;
 };
 
+// Has one non-virtual public base class at offset zero
 class __si_class_type_info
     : public __class_type_info
 {
@@ -57,6 +61,8 @@
     const __class_type_info* __base_type;
 
     virtual ~__si_class_type_info();
+
+    virtual void display(const void* obj) const;
 };
 
 struct __base_class_type_info
@@ -68,11 +74,14 @@
     enum __offset_flags_masks
     {
         __virtual_mask = 0x1,
-        __public_mask  = 0x2,
+        __public_mask  = 0x2, // base is public
         __offset_shift = 8
     };
+
+    void display(const void* obj) const;
 };
 
+// Has one or more base classes
 class __vmi_class_type_info
     : public __class_type_info
 {
@@ -83,11 +92,15 @@
 
     enum __flags_masks
     {
-        __non_diamond_repeat_mask = 0x1,
-        __diamond_shaped_mask     = 0x2
+        __non_diamond_repeat_mask = 0x1,  // has two or more distinct base class
+                                          //    objects of the same type
+        __diamond_shaped_mask     = 0x2   // has base class object with two or
+                                          //    more derived objects
     };
 
     virtual ~__vmi_class_type_info();
+
+    virtual void display(const void* obj) const;
 };
 
 class __pbase_type_info





More information about the cfe-commits mailing list