您的位置:首页 > 其它

学习 LLVM(2) isa<> 模板函数

2012-07-25 21:17 120 查看
http://llvm.org/docs/ProgrammersManual.html 开始学习的话,遇到的第一个 api 是 isa<>,
不仔细学习下好像也看不懂后面的程序吧?

isa<> 是一个模板函数,定义在 llvm/include/llvm/Support/Casting.h 中。其工作类似于
java 中的 "instanceof" 操作符。它判定一个指针或一个引用是否是指定类的实例。参见:
http://llvm.org/docs/ProgrammersManual.html#isa

定义:
template <class X, class Y>
inline bool isa(const Y &Val) { ... }

使用例:
if (isa<Type>(myVal)) { ... }

== 实现机理 ==

=== simplify_type<> ===
模板 template <T> struct simplify_type 用于提供 SimpleType 定义和 getSimplifiedValue() 函数。但是其特化版本 simplify_type<const T> 却似乎不是很正确?(其 getSimplifiedValue() 函数不能被编译通过?)

需要将其中的 static_cast<> 变为 const_cast<> 才能编译通过,可能是一个错误?

在其它类的定义中,可能为配合 isa<> 等,实现有自己的 simplify_type<> 特化版。需要我们在看到哪些类的时候,才能深入理解这个模板的更多用途。而且它们在特化版本中也有用 static_cast<> 的,可是我觉得那也同样无法编译通过?

=== 辅助模板 isa_impl<> ===
isa_impl<TO, FROM> 用于帮助实现 isa<X>. 实际计算 TO::classof(const FROM* p) <br>
这意味着,让类 TO 判断指针 p 所指向的对象是否为 TO 类型的。

实际实现中,对于一个类的继承结构如 B 继承 A,如果 p 指针指向的对象是 B, TO 为 B, FROM 为 A,则需要 classof() 函数能够实际判定出 p 确实是 B 对象,即使 p 当前的指针类型为 A*。具体如何实现 classof() 函数,我们在研究 LLVM 中的 Value 类及其派生体系的时候具体进行。那里使用了一种较为传统的 subClassID 的方式来识别子类类型。

=== 辅助模板 isa_impl_cl<> ===
isa_impl_cl<TO, FROM> 用于调用 isa_impl<>, 其特化 FROM 的多种版本,使得对 isa_impl<> 的调用成为有效的。有效的指 isa_impl<> 内调用 TO::classof() 能够给出正确的参数形式和类型。

本模板的特化版本有:
* template <To, From> struct isa_impl_cl<To, const From>
* template <To, From> struct isa_impl_cl<To, From*>
* template <To, From> struct isa_impl_cl<To, const From*>
* template <To, From> struct isa_impl_cl<To, const From * const>

=== 辅助模板 isa_impl_wrap<> ===
模板类 isa_impl_wrap<To, From, SimpleFrom> 实现对 isa_impl_cl<To, From> 的调用。
其中如果 From == SimpleFrom 使用的特化版本会直接调用 isa_impl_cl。

如果 From != SimpleFrom,则麻烦出在这里,我使用的测试例子如 isa_impl_wrap<A, B, const B> 会导致无法编译,或者导致使用 simplify_type<> 无法编译。我觉得这里要么模板有问题,要么模板要求传入的类参数 SimpleFrom 有特定的要求,但是没有注释。也许看到别的地方才能彻底理解这里。

=== 模板函数 isa<> ===
定义为 template <class X, class Y> inline bool isa(const Y &Val)。

设 YY = simplify_type<Y>::SimpleType,一般就是 Y。则 isa<X, Y>
实际实现调用为 isa_impl_wrap<X, Y, YY>。

对于特定类,如 Optional<T>,它实现了对 simplify_type< Optional<T> > 的特化版本,这样导致 Y != YY。也即导致对 isa_impl_wrap<> 的普通版本的调用。具体到研究 Optional<T> 的时候我再仔细看这里吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  LLVM