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<X,Y*>::ret_type_cast_or_null(Y *Val) {
204 if (Val == 0) return0;
205 assert(isa<X>(Val) && "cast_or_null<Ty>()argument of incompatible type!");
206 returncast<X>(Val);
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<To,From,
159 typenamesimplify_type<From>::SimpleType>::ret_typeret_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<To,SimpleFrom>::ret_type ret_type;
148 };
149
150 template<class To, classFromTy>
151 structcast_retty_wrap<To, FromTy, FromTy> {
152 // When thesimplified type is equal to the from type, use it directly.
153 typedef typename cast_retty_impl<To,FromTy>::ret_typeret_type;
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<From>::getSimplifiedValue(static_cast<From&>(Val));
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<To, const From> {
126 typedef const To &ret_type; // Normal case,return Ty&
127 };
128
129 template<class To, classFrom> struct cast_retty_impl<To,From*> {
130 typedef To*ret_type; // Pointer arg case, return Ty*
131 };
132
133 template<class To, classFrom> struct cast_retty_impl<To, const From*> {
134 typedef const To* ret_type; // Constant pointer arg case, return const Ty*
135 };
136
137 template<class To, classFrom> struct cast_retty_impl<To, const From*const>{
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<X, Y, typenamesimplify_type<Y>::SimpleType>::doit(Val);
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<To, SimpleFrom,
90 typename simplify_type<SimpleFrom>::SimpleType>::doit(
91 simplify_type<From>::getSimplifiedValue(Val));
92 }
93 };
94
95 template<typename To, typenameFromTy>
96 struct isa_impl_wrap<To,FromTy, FromTy> {
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<To,FromTy>::doit(Val);
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<To, From>::doit(Val);
58 }
59 };
60
61 template <typename To, typenameFrom> struct isa_impl_cl<To, const From> {
62 static inline bool doit(constFrom &Val) {
63 return isa_impl<To, From>::doit(Val);
64 }
65 };
66
67 template <typename To, typenameFrom> struct isa_impl_cl<To, From*> {
68 static inline bool doit(constFrom *Val) {
69 return isa_impl<To, From>::doit(*Val);
70 }
71 };
72
73 template <typename To, typenameFrom> struct isa_impl_cl<To, const From*> {
74 static inline bool doit(constFrom *Val) {
75 return isa_impl<To, From>::doit(*Val);
76 }
77 };
78
79 template <typename To, typenameFrom> struct isa_impl_cl<To, const From*const>{
80 static inline bool doit(constFrom *Val) {
81 return isa_impl<To, From>::doit(*Val);
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<X,Y>::ret_type cast (const Y&Val) {
194 assert(isa<X>(Val) && "cast<Ty>() argument ofincompatible type!");
195 return cast_convert_val<X, Y,
196 typename simplify_type<Y>::SimpleType>::doit(Val);
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<To,From>::ret_type doit(const From &Val) {
168 returncast_convert_val<To, SimpleFrom,
169 typenamesimplify_type<SimpleFrom>::SimpleType>::doit(
170 simplify_type<From>::getSimplifiedValue(Val));
171 }
172 };
173
174 template<class To, class FromTy>struct cast_convert_val<To,FromTy,FromTy>{
175 // This _is_ asimple type, just cast it.
176 static typenamecast_retty<To, FromTy>::ret_type doit(const FromTy &Val) {
177 typename cast_retty<To,FromTy>::ret_type Res2
178 = (typename cast_retty<To,FromTy>::ret_type)const_cast<FromTy&>(Val);
179 return Res2;
180 }
181 };
利用isa与cast,构建了另一个对应C++的dynamic_cast操作符的dyn_cast函数。
218 template <class X, class Y>
219 inline typename cast_retty<X,Y>::ret_type dyn_cast (constY &Val) {
220 return isa<X>(Val) ? cast<X, Y>(Val) :0;
221 }