Update contrib.
1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "ARM EABI LICENCE.txt"
5 // which accompanies this distribution, and is available
6 // in kernel/eka/compsupp.
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32/compsupp/symaehabi/symbian_rtti.cpp
19 #include "unwind_env.h"
21 #include "symbian_support.h"
23 // For information about these classes, se
24 // www.codesourcery.com/public/cxx-abi/abi.html#rtti.
25 using abi::__class_type_info;
26 using abi::__si_class_type_info;
27 using abi::__vmi_class_type_info;
28 using abi::__base_class_type_info;
31 // Given base class info (aBaseInfo) and a derived object pointer (aDerivedObj),
32 // this function implements "cast to base" and stores result in aBaseObj. This
33 // essentially sets aBaseObj to point to a memory location that represents
34 // aDerivedObj as the given base class. This function requires that aBaseInfo
35 // describes a base class of the aDerivedObj's class.
36 static void _CastUp(const __base_class_type_info& aBaseInfo, TAny** aDerivedObj, TAny** aBaseObj)
38 // Guard against a null pointer for aDerivedObj
39 if ( ! (*aDerivedObj) )
45 TInt offset = aBaseInfo.__offset_flags >> aBaseInfo.__offset_shift;
47 if (aBaseInfo.__offset_flags & aBaseInfo.__virtual_mask)
49 // For virtual bases, look up offset in vtable + offset.
51 // Get vtbl pointer as the first 4 bytes of **aDerivedObj
52 TUint32* vptr = (TUint32*) ( *( (TUint32*) (*aDerivedObj) ) );
54 offset = *( vptr + offset / sizeof(TUint32) );
58 *aBaseObj = (TAny*) ( ( (TUint8*) *aDerivedObj ) + offset );
62 // For a description of this function, see comments in unwind_env.h.
63 extern "C" TBool _DoDerivedToBaseConversion(const std::type_info* aDerivedType,
64 const std::type_info* aBaseType,
69 const std::type_info& type_base_type = typeid(*aBaseType);
70 const std::type_info& type_derived_type = typeid(*aDerivedType);
72 // We must proceed depending on the type of the type_info objects for derived
74 if ( type_derived_type == typeid(__si_class_type_info) )
76 // The __si_class_type_info means that the derived type has a single,
77 // public, non-virtual base, and that the base is at offset zero. We should
78 // be able to simply compare the base type from __si_class_type_info with
81 const __si_class_type_info* derived = (const __si_class_type_info*) aDerivedType;
83 if ( *(derived->__base_type) == *aBaseType )
85 // The types match, work done.
86 *aBaseObj = *aDerivedObj;
91 // The types don't match. We should proceed to comparison with the any
92 // classes. In this case there is a single base as follows:
93 const __class_type_info* bType = derived->__base_type;
95 // No pointer adjustment required for __si_class_type_info.
96 return _DoDerivedToBaseConversion(bType, aBaseType, aDerivedObj, aBaseObj);
99 else if ( type_derived_type == typeid(__vmi_class_type_info) )
101 // The __vmi_class_type_info is for all other scenarios. We get an array of
102 // bases which we need to traverse and do comparison on.
104 const __vmi_class_type_info* derived = (const __vmi_class_type_info*)aDerivedType;
106 const unsigned count = derived->__base_count;
108 for ( unsigned i = 0; i < count; i++ )
110 // Get the base info for this base class
111 const __base_class_type_info bInfo = derived->__base_info[i];
113 if ( ! ( bInfo.__offset_flags & bInfo.__public_mask) )
115 // The base is non-public base, so the remainder of the hierarchy
116 // above this base is of no interest
120 // Get the class type info for this base
121 const __class_type_info* bType = bInfo.__base_type;
123 // First check if the type from the list corresponds to requested base
125 if ( (*bType) == (*aBaseType) )
127 // Match! Convert the pointer to point to the base.
128 _CastUp(bInfo, aDerivedObj, aBaseObj);
132 // No match, we must now recursively delve into superclasses of bType.
133 // To do that, we need to advance the derived class pointer to point to
134 // the current base class as in bInfo.
136 _CastUp(bInfo, aDerivedObj, &newDerivedPtr);
138 // Now go recursive, substituting aDerivedObj with adjusted pointer and bType instead of aDerivedType
139 TBool result = _DoDerivedToBaseConversion(bType, aBaseType, (TAny**)(&newDerivedPtr), aBaseObj);
141 // Return only if the match is found, otherwise continue with the loop
144 // Match came back from recursion, pass up.
148 // No match from recursion, advance to next base.
156 // No match was found for aBaseType in the aDerivedType's ancestry.