Llvm内置了一个类型转换系统,并定义了类似于dynamic_cast这样的转换函数。Llvm底层的很大部分是由模板类构成的,这个转换系统对于模板类间的类型判断及转换至为重要。以下只是描述这个转换系统的一个框架,该系统的正确实现,还依赖于参与模板类正确实现某些函数(下面会提到)。
cast_or_null是llvm所提供的类型转换系统的部分,这是一个有趣的模板实现。这个实现在llvm-3.1/include/llvm/support/Casting.h。
202 template <class X, class Y>
203 inline typename cast_retty
204 if (Val == 0) return0;
205 assert(isa
206 returncast
207 }
首先,cast_or_null的返回类型是cast_retty中定义的ret_type类型。cast_retty只定义了ret_type(cast_retty顾名思义是cast return type的意思)。
156 template<class To, classFrom>
157 struct cast_retty{
158 typedef typename cast_retty_wrap 159 typenamesimplify_type 160 }; 这个ret_type则是typedef自cast_retty_wrap提供中定义的ret_type。 142 template<class To, class From,class SimpleFrom> 143 struct cast_retty_wrapp{ 144 // When thesimplified type and the from type are not the same, use the type 145 // simplifier toreduce the type, then reuse cast_retty_impl to get the 146 // resultant type. 147 typedef typename cast_retty 148 }; 149 150 template<class To, classFromTy> 151 structcast_retty_wrap 152 // When thesimplified type is equal to the from type, use it directly. 153 typedef typename cast_retty_impl 154 }; 看到cast_retty_wrap非特化版本在147行又递归回了cast_retty。这是怎么回事?在cast_retty定义的159行,simplify_type的定义如下: 30 template<typename From> struct simplify_type { 31 typedef From SimpleType; // The realtype this represents... 32 33 // An accessor toget the real value... 34 staticSimpleType &getSimplifiedValue(From &Val) { returnVal; } 35 }; 36 37 template<typename From> structsimplify_type<const From> { 38 typedef const From SimpleType; 39 staticSimpleType &getSimplifiedValue(const From&Val) { 40 returnsimplify_type 41 } 42 }; 类型SimpleType就是参数From。不过这只是Casting.h提供的默认实现,这个类的本义是提供类型简化,实际上在llvm及Clang的许多地方都另外提供了特化的simplify_type的定义,那么147行cast_retty的每次递归都将化简类型一次,直到无法化简(即调用上面的默认simplify_type实现),这时142行的类型From与SimpleFrom相同,因此使用cast_retty_wrap在150行的特化形式,进而由cast_retty_impl确定该类型。 122 template<class To, classFrom> struct cast_retty_impl { 123 typedefTo& ret_type; // Normal case, return Ty& 124 }; 125 template<class To, classFrom> struct cast_retty_impl 126 typedef const To &ret_type; // Normal case,return Ty& 127 }; 128 129 template<class To, classFrom> struct cast_retty_impl 130 typedef To*ret_type; // Pointer arg case, return Ty* 131 }; 132 133 template<class To, classFrom> struct cast_retty_impl 134 typedef const To* ret_type; // Constant pointer arg case, return const Ty* 135 }; 136 137 template<class To, classFrom> struct cast_retty_impl 138 typedef const To* ret_type; // Constant pointer arg case, return const Ty* 139 }; 为什么要采用这么复杂的返回值类型声明呢?因为C++制订的类型转换规则仅允许调用用户定义的转换操作符一次,而这里则不限制转换的次数,只要给出simplify_type的特化实现,当然这样存在cast_retty陷入无限递归的情形(实际上无限递归是不存在的,因为C++限制了模板嵌套的层数,GCC好像是128)。 Isa函数的作用是测试给定的变量是否具有指定的类型。 108 template <class X, class Y> 109 inline bool isa(const Y &Val) { 110 return isa_impl_wrap 111 } 这里再次应用了simplify_type来简化类型Y,并作为模板参数SimpleFrom的实参调用下面的函数。 84 template<typename To, typenameFrom, typename SimpleFrom> 85 struct isa_impl_warp { 86 // When From !=SimplifiedType, we can simplify the type some more by using 87 // thesimplify_type template. 88 static booldoit(const From &Val) { 89 returnisa_impl_wrap 90 typename simplify_type 91 simplify_type 92 } 93 }; 94 95 template<typename To, typenameFromTy> 96 struct isa_impl_wrap 97 // When From ==SimpleType, we are as simple as we are going to get. 98 static booldoit(const FromTy &Val) { 99 return isa_impl_cl 100 } 101 }; 在89行对isa_impl_wrap的调用中,也再次使用simplify_type对Y的化简类型(SimpleFrom)进行类型化简。同时对给定的值进行转换(通过getSimplifiedValue,91行)。一旦From与SimpleFrom达成一致,isa_impl_wrap的doit方法(98行)调用isa_impl_cl的对应的方法。 54 template <typename To, typenameFrom> struct isa_impl_cl { 56 static inline bool doit(constFrom &Val) { 57 return isa_impl 58 } 59 }; 60 61 template <typename To, typenameFrom> struct isa_impl_cl 62 static inline bool doit(constFrom &Val) { 63 return isa_impl 64 } 65 }; 66 67 template <typename To, typenameFrom> struct isa_impl_cl 68 static inline bool doit(constFrom *Val) { 69 return isa_impl 70 } 71 }; 72 73 template <typename To, typenameFrom> struct isa_impl_cl 74 static inline bool doit(constFrom *Val) { 75 return isa_impl 76 } 77 }; 78 79 template <typename To, typenameFrom> struct isa_impl_cl 80 static inline bool doit(constFrom *Val) { 81 return isa_impl 82 } 83 }; 上面所有的定义都调用下面这个类的doit方法。 47 template <typename To, typenameFrom> 48 struct isa_impl { 49 static inline bool doit(constFrom &Val) { 50 returnTo::classof(&Val); 51 } 52 }; 为了实现isa,涉及的类必须定义50行的classof静态成员函数。当然classof的语义由定义它的类来决定,这带来了很高的灵活性。比如,我们不仅可以声明派生类isa基类,甚至不相关的类也可以声明为isa关系。 cast函数的定义也是类似的。 192 template <class X, class Y> 193 inline typename cast_retty 194 assert(isa 195 return cast_convert_val 196 typename simplify_type 197 } 注意178行的const_cast。到这里我们可以明白,所谓的cast过程是依靠simplify_type的机制实现的。还有,const_cast之前是C形式的强制类型转换,不过前面cast_convert_val的递归调用能保证Val(注意通过getSimplifiedValue转换)与这个类型相容。 165 template<class To, class From,class SimpleFrom> struct cast_convert_val { 166 // This is not asimple type, use the template to simplify it... 167 static typename cast_retty 168 returncast_convert_val 169 typenamesimplify_type 170 simplify_type 171 } 172 }; 173 174 template<class To, class FromTy>struct cast_convert_val 175 // This _is_ asimple type, just cast it. 176 static typenamecast_retty 177 typename cast_retty 178 = (typename cast_retty 179 return Res2; 180 } 181 }; 利用isa与cast,构建了另一个对应C++的dynamic_cast操作符的dyn_cast函数。 218 template <class X, class Y> 219 inline typename cast_retty 220 return isa 221 } isa函数
cast函数
dyn_cast函数