Llvm的类型转换系统

Llvm内置了一个类型转换系统,并定义了类似于dynamic_cast这样的转换函数。Llvm底层的很大部分是由模板类构成的,这个转换系统对于模板类间的类型判断及转换至为重要。以下只是描述这个转换系统的一个框架,该系统的正确实现,还依赖于参与模板类正确实现某些函数(下面会提到)。

cast_retty类

cast_or_null是llvm所提供的类型转换系统的部分,这是一个有趣的模板实现。这个实现在llvm-3.1/include/llvm/support/Casting.h。

 

202   template <class X, class Y>

203   inline typename cast_retty::ret_type_cast_or_null(Y *Val) {

204     if (Val == 0) return0;

205     assert(isa(Val) && "cast_or_null()argument of incompatible type!");

206     returncast(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

159                      typenamesimplify_type::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::ret_type ret_type;

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::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::getSimplifiedValue(static_cast(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_implconst From> {

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_implconst From*> {

134     typedef const To* ret_type;  // Constant pointer arg case, return const Ty*

135   };

136  

137   template<class To, classFrom> struct cast_retty_implconst 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函数

Isa函数的作用是测试给定的变量是否具有指定的类型。

 

108   template <class X, class Y>

109   inline bool isa(const Y &Val) {

110     return isa_impl_wrap typenamesimplify_type::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

90           typename simplify_type::SimpleType>::doit(

91                              simplify_type::getSimplifiedValue(Val));

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::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::doit(Val);

58       }

59     };

60    

61     template <typename To, typenameFrom> struct isa_impl_clconst From> {

62       static inline bool doit(constFrom &Val) {

63         return isa_impl::doit(Val);

64       }

65     };

66    

67     template <typename To, typenameFrom> struct isa_impl_cl {

68       static inline bool doit(constFrom *Val) {

69         return isa_impl::doit(*Val);

70       }

71     };

72    

73     template <typename To, typenameFrom> struct isa_impl_clconst From*> {

74       static inline bool doit(constFrom *Val) {

75         return isa_impl::doit(*Val);

76       }

77     };

78    

79     template <typename To, typenameFrom> struct isa_impl_clconst From*const>{

80       static inline bool doit(constFrom *Val) {

81         return isa_impl::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函数

cast函数的定义也是类似的。

 

192   template <class X, class Y>

193   inline typename cast_retty::ret_type cast (const Y&Val) {

194     assert(isa(Val) && "cast() argument ofincompatible type!");

195     return cast_convert_val

196                            typename simplify_type::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::ret_type doit(const From &Val) {

168       returncast_convert_val

169         typenamesimplify_type::SimpleType>::doit(

170                            simplify_type::getSimplifiedValue(Val));

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::ret_type doit(const FromTy &Val) {

177       typename cast_retty::ret_type Res2

178        = (typename cast_retty::ret_type)const_cast(Val);

179       return Res2;

180     }

181   };

dyn_cast函数

利用isa与cast,构建了另一个对应C++的dynamic_cast操作符的dyn_cast函数。

 

218   template <class X, class Y>

219   inline typename cast_retty::ret_type dyn_cast (constY &Val) {

220     return isa(Val) ? cast(Val) :0;

221   }

 

你可能感兴趣的:(LLVM)