Studying note of GCC-3.4.6 source (65)

4.3.1.7.8.2.2.              Generate nodes of type­_info definition

Below it will construct these type_info type series. First is the base class.

 

1251   static void

1252   create_tinfo_types (void)                                                                                 in rtti.c

1253   {

1254     my_friendly_assert (!ti_desc_type_node, 20020609);

1255  

1256     push_nested_namespace (abi_node);

 

If we need put a namespace in effective which is not enclosed by current namespace (for example, currently A::B, now we expect A::D), we should uses push_nested_namespace instead of push_namespace. By recursing, the function first returns back global namespace, caches content from current namespace to global namespace by push_to_top_level, then pushes content from global namespace to the expected namespace by push_namespace iteratively (refer to Enter global namespace).

 

3143   void

3144   push_nested_namespace (tree ns)                                                       in name-lookup.c

3145   {

3146     if (ns == global_namespace)

3147       push_to_top_level ();

3148     else

3149     {

3150       push_nested_namespace (CP_DECL_CONTEXT (ns));

3151       push_namespace (DECL_NAME (ns));

3152     }

3153   }

 

The reverse operation to push_nested_namespace is pop_nested_namespace. All identifiers cached are restored (refer to Return from global namespace).

 

3158   void

3159   pop_nested_namespace (tree ns)                                                         in name-lookup.c

3160   {

3161     timevar_push (TV_NAME_LOOKUP);

3162     while (ns != global_namespace)

3163     {

3164       pop_namespace ();

3165       ns = CP_DECL_CONTEXT (ns);

3166     }

3167  

3168     pop_from_top_level ();

3169     timevar_pop (TV_NAME_LOOKUP);

3170   }

 

Now we are in __cxxabiv1 namespace. In directoty “gcc-3.4.6/libstdc++-v3/libsupc++”, there is head file “cxxabi.h”. This file is also found at “c++/`version`/cxxabi.h” under include directory in Linux, and the implementation is generated into library “libstdc++.so.`ver`”. The compiler is going to generate the class definitions following the file content.

In __cxxabiv1 namespace, the classes all derive from std::type_info. So it first needs create this base. But note that in below, the base is constructed within __cxxabiv1 namespace, and its name is “type_info_pseudo”. In fact, in GCC, no real std::type_info generated. In std::type_info definition below, can see that this class can’t be used alone but as base, and it has trivial destructor (though it is virtual). As those get used are derived classes in __cxxabiv1, thus it is feasible to use  type_info_pseudo replacing std::type_info, as long as the methods and members used have the same declarations, and not use base pointer (compiler guarantees this). Below, it can see that type type_info_pseudo has been greatly simplified.

 

create_tinfo_types (continue)

 

1258     /* Create the internal type_info structure. This is used as a base for

1259       the other structures.  */

1260     {

1261       tree field, fields;

1262  

1263       ti_desc_type_node = make_aggr_type (RECORD_TYPE);

1264       field = build_decl (FIELD_DECL, NULL_TREE, const_ptr_type_node);

1265       fields = field;

1266      

1267       field = build_decl (FIELD_DECL, NULL_TREE, const_string_type_node);

1268       TREE_CHAIN (field) = fields;

1269       fields = field;

1270      

1271       finish_builtin_struct (ti_desc_type_node, "__type_info_pseudo",

1272                        fields, NULL_TREE);

1273       TYPE_HAS_CONSTRUCTOR (ti_desc_type_node) = 1;

1274     }

 

Class type_info_pseudo has two anoymous data members, one is of type “const void*”, the other is “const char*”. It aims to make type_info_pseudo has the same size as std::type_info (note that std::type_info has vtable, its size equates to that of const void*). Function finish_builtin_struct finalizes the struct.

 

1476   void

1477   finish_builtin_struct (tree type, const char *name, tree fields,                      in stor-layout.c

1478                      tree align_type)

1479   {

1480     tree tail, next;

1481  

1482     for (tail = NULL_TREE; fields; tail = fields, fields = next)

1483     {

1484       DECL_FIELD_CONTEXT (fields) = type;

1485       next = TREE_CHAIN (fields);

1486       TREE_CHAIN (fields) = tail;

1487     }

1488     TYPE_FIELDS (type) = tail;

1489  

1490     if (align_type)

1491     {

1492       TYPE_ALIGN (type) = TYPE_ALIGN (align_type);

1493       TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (align_type);

1494     }

1495  

1496     layout_type (type);

1497   #if 0 /* not yet, should get fixed properly later */

1498     TYPE_NAME (type) = make_type_decl (get_identifier (name), type);

1499   #else

1500     TYPE_NAME (type) = build_decl (TYPE_DECL, get_identifier (name), type);

1501   #endif

1502     TYPE_STUB_DECL (type) = TYPE_NAME (type);

1503     layout_decl (TYPE_NAME (type), 0);

1504   }

 

Below is the definition of std::type_info. As comparison, type_info_pseudo doesn’t define any method, and only has unusable anonymous member. Why?

 

63      class type_info                                                                                        in typeinfo

64      {

65        public:

66          /** Destructor. Being the first non-inline virtual function, this

67           *  controls in which translation unit the vtable is emitted. The

68           *  compiler makes use of that information to know where to emit

69           *  the runtime-mandated type_info structures in the new-abi.  */

70          virtual ~type_info();

71     

72       private:

73          /// Assigning type_info is not supported. Made private.

74          type_info& operator=(const type_info&);

75          type_info(const type_info&);

76         

77       protected:

78          const char *__name;

79         

80        protected:

81          explicit type_info(const char *__n): __name(__n) { }

82         

83       public:

84          // the public interface

85          /** Returns an @e implementation-defined byte string; this is not

86           * portable between compilers!  */

87          const char* name() const

88          { return __name; }

89     

90      #if !__GXX_MERGED_TYPEINFO_NAMES

91          bool before(const type_info& __arg) const;

92          // In old abi, or when weak symbols are not supported, there can

93          // be multiple instances of a type_info object for one

94          // type. Uniqueness must use the _name value, not object address.

95          bool operator==(const type_info& __arg) const;

96      #else

97          /** Returns true if @c *this precedes @c __arg in the implementation's

98           * collation order.  */

99          // In new abi we can rely on type_info's NTBS being unique,

100        // and therefore address comparisons are sufficient.

101        bool before(const type_info& __arg) const

102        { return __name < __arg.__name; }

103        bool operator==(const type_info& __arg) const

104        { return __name == __arg.__name; }

105    #endif

106        bool operator!=(const type_info& __arg) const

107        { return !operator==(__arg); }

108       

109        // the internal interface

110       public:

111         // return true if this is a pointer type of some kind

112         virtual bool __is_pointer_p() const;

113         // return true if this is a function type

114         virtual bool __is_function_p() const;

115    

116         // Try and catch a thrown type. Store an adjusted pointer to the

117         // caught type in THR_OBJ. If THR_TYPE is not a pointer type, then

118         // THR_OBJ points to the thrown object. If THR_TYPE is a pointer

119         // type, then THR_OBJ is the pointer itself. OUTER indicates the

120        // number of outer pointers, and whether they were const

121        // qualified.

122        virtual bool __do_catch(const type_info *__thr_type, void **__thr_obj,

123                           unsigned __outer) const;

124   

125        // internally used during catch matching

126        virtual bool __do_upcast(const __cxxabiv1::__class_type_info *__target,

127                            void **__obj_ptr) const;

128    };

 

First, downcasting from derived pointer to base pointer needsn’t RTTI supports. The derived contains enough information, the procedure we will see later. While for upcasting from base pointer to derived pointer, in C++, there are 2 ways, one is via force-casting of C style, which won’t take any type checking; the other is by dynamic_cast operator, which is a library function accepting type_info objects as paramter. Abother place C++ will make upcasting, is the catched object in catch expression, for which the compiler will invoke dynamic_cast automatically. So as long as the front-end guarantes before handing to the back-end for emitting assemble, the arguments of dynamic_cast are real type_info objects instead the pseudo type_info objects here, it is OK (as the methods of real type_info are also in the library). Behind, can that the compiler follows this way, at the last step of the front-end processing, it replaces pseudo type_info objects with the real ones (thus, it is key for both have the same size).

Next, it is going to define pseudo type_info derived class and pseudo helper class matching those in__cxxabiv1 namespace. The criterion is also: of the same size of the real type.

 

create_tinfo_types (continue)

 

1276     /* Fundamental type_info */

1277     bltn_desc_type_node = create_pseudo_type_info

1278         ("__fundamental_type_info", 0,

1279          NULL);

1280  

1281     /* Array, function and enum type_info. No additional fields.  */

1282     ary_desc_type_node = create_pseudo_type_info

1283         ("__array_type_info", 0,

1284          NULL);

1285     func_desc_type_node = create_pseudo_type_info

1286          ("__function_type_info", 0,

1287           NULL);

1288     enum_desc_type_node = create_pseudo_type_info

1289          ("__enum_type_info", 0,

1290           NULL);

1291    

1292    /* Class type_info. Add a flags field.  */

1293     class_desc_type_node = create_pseudo_type_info

1294           ("__class_type_info", 0,

1295            NULL);

1296    

1297     /* Single public non-virtual base class. Add pointer to base class.

1298       This is really a descendant of __class_type_info.  */

1299     si_class_desc_type_node = create_pseudo_type_info

1300              ("__si_class_type_info", 0,

1301               build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type),

1302               NULL);

1303    

1304     /* Base class internal helper. Pointer to base type, offset to base,

1305       flags.  */

1306     {

1307       tree field, fields;

1308      

1309       field = build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type);

1310       fields = field;

1311      

1312       field = build_decl (FIELD_DECL, NULL_TREE, integer_types[itk_long]);

1313       TREE_CHAIN (field) = fields;

1314       fields = field;

1315    

1316       base_desc_type_node = make_aggr_type (RECORD_TYPE);

1317       finish_builtin_struct (base_desc_type_node, "__base_class_type_info_pseudo",

1318                         fields, NULL_TREE);

1319       TYPE_HAS_CONSTRUCTOR (base_desc_type_node) = 1;

1320     }

1321    

1322     /* General hierarchy is created as necessary in this vector.  */

1323     vmi_class_desc_type_node = make_tree_vec (10);

1324    

1325    /* Pointer type_info. Adds two fields, qualification mask

1326       and pointer to the pointed to type. This is really a descendant of

1327       __pbase_type_info.  */

1328     ptr_desc_type_node = create_pseudo_type_info

1329         ("__pointer_type_info", 0,

1330          build_decl (FIELD_DECL, NULL_TREE, integer_type_node),

1331          build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type),

1332          NULL);

1333  

1334     /* Pointer to member data type_info. Add qualifications flags,

1335       pointer to the member's type info and pointer to the class.

1336       This is really a descendant of __pbase_type_info.  */

1337     ptm_desc_type_node = create_pseudo_type_info

1338          ("__pointer_to_member_type_info", 0,

1339           build_decl (FIELD_DECL, NULL_TREE, integer_type_node),

1340           build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type),

1341           build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type),

1342           NULL);

1343  

1344     pop_nested_namespace (abi_node);

1345   }

 

The creation of these derived classes is done by create_pseudo_type_info below. In C++, non-vritual base to derived class is the same as data member. In GCC implementation, it processes this way. Below at line 1132, the pseudo type_info is added in the derived as the base.

 

1112   static tree

1113   create_pseudo_type_info (const char *real_name, int ident, ...)                           in rtti.c

1114   {

1115     tree pseudo_type;

1116     char *pseudo_name;

1117     tree fields;

1118     tree field_decl;

1119     tree result;

1120     va_list ap;

1121  

1122     va_start (ap, ident);

1123  

1124    /* Generate the pseudo type name.  */

1125     pseudo_name = alloca (strlen (real_name) + 30);

1126     strcpy (pseudo_name, real_name);

1127     strcat (pseudo_name, "_pseudo");

1128     if (ident)

1129       sprintf (pseudo_name + strlen (pseudo_name), "%d", ident);

1130    

1131    /* First field is the pseudo type_info base class.  */

1132     fields = build_decl (FIELD_DECL, NULL_TREE, ti_desc_type_node);

1133    

1134    /* Now add the derived fields.  */

1135     while ((field_decl = va_arg (ap, tree)))

1136     {

1137       TREE_CHAIN (field_decl) = fields;

1138       fields = field_decl;

1139     }

1140    

1141     /* Create the pseudo type.  */

1142     pseudo_type = make_aggr_type (RECORD_TYPE);

1143     finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE);

1144     CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type;

1145  

1146     result = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);

1147     TINFO_REAL_NAME (result) = get_identifier (real_name);

1148     TINFO_PSEUDO_TYPE (result) =

1149       cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST);

1150    

1151     va_end (ap);

1152     return result;

1153   }

 

Note, here parameter real_name passed in create_pseudo_type_info is the name of real type_info derived class. At line 1147, this name is set into TINFO_REAL_NAME field of the pseudo type_info derived class, which will guide the compiler to generate the object expected by dynamic_cast.

4.3.1.7.8.2.3.              Using RTTI

4.3.1.7.8.2.3.1.        Build RTTI for class

Only when user define class with virtual function, the compiler will generate type_info object. Or when the compiler sees dynamic_cast, it will also generate type_info object for both types. The creation is done by get_tinfo_decl. Here the parameter type is the class needs type_info object (type_info is exchangable with tinfo below).

 

317    tree

318    get_tinfo_decl (tree type)                                                                          in class.c

319    {

320      tree name;

321      tree d;

322   

323      if (COMPLETE_TYPE_P (type)

324         && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)

325      {

326        error ("cannot create type information for type `%T' because its size is variable",

327             type);

328        return error_mark_node;

329      }

330   

331      if (TREE_CODE (type) == METHOD_TYPE)

332        type = build_function_type (TREE_TYPE (type),

333                               TREE_CHAIN (TYPE_ARG_TYPES (type)));

334   

335      /* For a class type, the variable is cached in the type node

336        itself.  */

337      if (CLASS_TYPE_P (type))

338      {

339        d = CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type));

340        if (d)

341          return d;

342      }

343       

344      name = mangle_typeinfo_for_type (type);

345   

346     d = IDENTIFIER_GLOBAL_VALUE (name);

347      if (!d)

348      {

349        tree var_desc = get_pseudo_ti_desc (type);

350   

351        d = build_lang_decl (VAR_DECL, name, TINFO_PSEUDO_TYPE (var_desc));

352         

353        DECL_ARTIFICIAL (d) = 1;

354        TREE_READONLY (d) = 1;

355        TREE_STATIC (d) = 1;

356        DECL_EXTERNAL (d) = 1;

357        DECL_COMDAT (d) = 1;

358        TREE_PUBLIC (d) = 1;

359        SET_DECL_ASSEMBLER_NAME (d, name);

360   

361        pushdecl_top_level_and_finish (d, NULL_TREE);

362   

363        if (CLASS_TYPE_P (type))

364          CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (type)) = d;

365   

366        /* Remember the type it is for.  */

367        TREE_TYPE (name) = type;

368   

369        /* Add decl to the global array of tinfo decls.  */

370        my_friendly_assert (unemitted_tinfo_decls != 0, 20030312);

371        VARRAY_PUSH_TREE (unemitted_tinfo_decls, d);

372      }

373   

374      return d;

375    }

 

At line 344, mangle_typeinfo_for_type returns the unique identifier for the tinfo of the type with mangled name (mangled name of tinfo besides follows the mangling of normal entity will have a leading “TI”). Tinfo is public static member of the class, and it uses mangled name. Thus as soon as built, it will be added into global namespace at line 361 without the risk of name collision. It greatly simplifies the searching of tinfos, code of line 346 is enough; otherwise it needs look into classes one after one with much less efficiency.

If the class hasn’t tinfo generated, it first needs get_pseudo_ti_desc to find out its type.

 

1159   static tree

1160   get_pseudo_ti_desc (tree type)                                                                          in rtti.c

1161   {

1162     switch (TREE_CODE (type))

1163     {

1164       case OFFSET_TYPE:

1165         return ptm_desc_type_node;

1166       case POINTER_TYPE:

1167         return ptr_desc_type_node;

1168       case ENUMERAL_TYPE:

1169         return enum_desc_type_node;

1170       case FUNCTION_TYPE:

1171         return func_desc_type_node;

1172       case ARRAY_TYPE:

1173         return ary_desc_type_node;

1174       case UNION_TYPE:

1175       case RECORD_TYPE:

1176         if (TYPE_PTRMEMFUNC_P (type))

1177           return ptm_desc_type_node;

1178         else if (!COMPLETE_TYPE_P (type))

1179         {

1180           if (!at_eof)

1181             cxx_incomplete_type_error (NULL_TREE, type);

1182           return class_desc_type_node;

1183         }

1184         else if (!CLASSTYPE_N_BASECLASSES (type))

1185           return class_desc_type_node;

1186         else

1187         {

1188           tree binfo = TYPE_BINFO (type);

1189           tree base_binfos = BINFO_BASETYPES (binfo);

1190           tree base_accesses = BINFO_BASEACCESSES (binfo);

1191           tree base_binfo = TREE_VEC_ELT (base_binfos, 0);

1192           int num_bases = TREE_VEC_LENGTH (base_binfos);

1193         

1194           if (num_bases == 1

1195              && TREE_VEC_ELT (base_accesses, 0) == access_public_node

1196              && !TREE_VIA_VIRTUAL (base_binfo)

1197              && integer_zerop (BINFO_OFFSET (base_binfo)))

1198             /* single non-virtual public.  */

1199             return si_class_desc_type_node;

1200           else

1201           {

1202             tree var_desc;

1203             tree array_domain, base_array;

1204             

1205             if (TREE_VEC_LENGTH (vmi_class_desc_type_node) <= num_bases)

1206             {

1207               int ix;

1208               tree extend = make_tree_vec (num_bases + 5);

1209                

1210               for (ix = TREE_VEC_LENGTH (vmi_class_desc_type_node); ix--;)

1211                 TREE_VEC_ELT (extend, ix)

1212                     = TREE_VEC_ELT (vmi_class_desc_type_node, ix);

1213               vmi_class_desc_type_node = extend;

1214             }

1215             var_desc = TREE_VEC_ELT (vmi_class_desc_type_node, num_bases);

1216             if (var_desc)

1217               return var_desc;

1218    

1219             /* Create the array of __base_class_type_info entries.

1220               G++ 3.2 allocated an array that had one too many

1221               entries, and then filled that extra entries with

1222               zeros.  */

1223             if (abi_version_at_least (2))

1224               array_domain = build_index_type (size_int (num_bases - 1));

1225             else

1226               array_domain = build_index_type (size_int (num_bases));

1227             base_array =

1228                    build_array_type (base_desc_type_node, array_domain);

1229  

1230             push_nested_namespace (abi_node);

1231             var_desc = create_pseudo_type_info

1232                        ("__vmi_class_type_info", num_bases,

1233                         build_decl (FIELD_DECL, NULL_TREE, integer_type_node),

1234                         build_decl (FIELD_DECL, NULL_TREE, integer_type_node),

1235                         build_decl (FIELD_DECL, NULL_TREE, base_array),

1236                         NULL);

1237             pop_nested_namespace (abi_node);

1238  

1239             TREE_VEC_ELT (vmi_class_desc_type_node, num_bases) = var_desc;

1240             return var_desc;

1241           }

1242         }

1243       default:

1244         return bltn_desc_type_node;

1245     }

1246   }

 

vmi_class_desc_type_node originally is created as empty array of size 10 which is used for multiple-derived class. In fact this is the array of descriptors with first entry for virutal derivation, and the rest filled with __vmi_class_type_info2, __vmi_class_type_info3 and so on for derived class of variant number of bases.

In RECORD_TYPE node, VAR_DECL nodes represents static members of the class. As soon as its creation, the tinfo object can be said ready, and is added in global namespace by pushdecl_top_level_and_finish. But we have seen that the tinfo generated here is pseudo object, which needs post-processing, so it is cached into unemitted_tinfo_decls.

 

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、下4载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、下4载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值