学习笔记 LLVM(3) cast<> 模板函数

cast<> 定义在 llvm/include/llvm/Support/[[Casting.h]], 参见 [[isa]]

== cast<> ==
操作符 cast<> 表示一个“带检查的类型转换”操作。它将一个基类的指针或引用转化为派生类的,如果指针或引用不是所给类型的实例则会产生一个断言失败。This should be used in cases where you have some information that makes you believe that something is of the right type. An example of the isa<> and cast<> template is:

<syntaxhighlight lang="cpp">
static bool isLoopInvariant(const Value *V, const Loop *L) {
  if (isa<Constant>(V) || isa<Argument>(V) || isa<GlobalValue>(V))
    return true;

  // Otherwise, it !MUST be an instruction...
  return !L->contains(cast<Instruction>(V)->getParent());
}
</syntaxhighlight>

(MUST 我标出该词,表示确信经过前面的 isa<> 检查,V 指针 '''一定''' 是 Instruction 类型的。)

== 实现机理 ==

=== 模板类 cast_retty_impl<TO, FROM> ===
用于计算 cast<> 的返回类型,其根据 FROM 类型、TO 类型计算。这个模板类通过特化处理
<const FROM>, <FROM *>, <const FROM*>, <const FROM* const> 等多种情况,从
而计算出正确的返回 ret_type。

=== 模板类 cast_retty_wrap<TO, FROM, SimpleFROM> ===
此模板用于根据 TO, FROM, SimpleFROM 三个模板参数计算出 cast<> 的返回类型。

当 FROM 类型和 SimpleFROM 类型不同的时候,使用 simplify_type 来简化 SimpleFROM 的
类型,并重新调用 cast_retty<> 来计算结果返回类型。(这里类似于 isa<> 中的计算)

当 FROM 类型和 SimpleFROM 类型相同时,使用 cast_retty_wrap<TO, FROM, FROM> 的
特化版本,则直接使用 FROM 对应的返回类型,使用 cast_retty_impl<TO, FROM> 实现。

=== 模板类 cast_retty<TO, FROM> ===
设 SimpleFROM = simplify_type<FROM>::SimpleType,则此模板类实际调用
cast_retty_wrap<TO, FROM, SimpleFROM> 来计算返回类型。一般而言,FROM == SimpleFROM。
(也类似于 isa<> 中的计算)

对于特定的类,如 Optional<T>,有自己特化的 simplify_type<> 实现,因而会导致
FROM != SimpleFROM,待学习 Optional 的时候,再仔细分析吧。

=== 模板类 cast_convert_val<TO, FROM, SimpleFROM> ===
其特化版本 cast_convert_val<TO, FROM, FROM> 提供的函数 doit(val),用于得到转换为
ret_type 的 val 值,这一转换简化写法为:
  FROM &f = const_cast<FROM&>(val);
  ret_type r = (ret_type)f;
其中第二步,使用的转换可以对任何不兼容的类型进行,实在不太安全?为何不用 static_cast 呢?

非特化版本 cast_convert_val<> 会使用 simplify_type<> 获得类型的非简单值(non-simple),
某些灵巧指针类(smart pointers)特化了 simplify_type<> 的实现,使得 FROM != SimpleFROM
的情况得以产生并处理。

=== cast<> ===
模板函数 cast<To>(const From &f) 转换指定参数 f 到所给类型 To。此转换(cast)操作将断言
类型是正确可转换的(使用 isa<> 模板函数来判定),因此其在失败的时候不是返回 null 而是产生
断言错。其不允许空指针作为参数,因为那样 isa<> 函数调用会发生保护错。例子:
  cast<Instruction>(myVal)->getParent()

实现时,调用 cast_convert_val<To, From, SimpleFrom>,其中 SimpleFrom =
simplify_type<From>::SimpleType。对于特定的 smart pointer 类,可能 From != SimpleFrom。

== 小结 ==
isa<>, cast<> 等模板类使用了多个辅助模板类来帮助计算返回类型、类型简化、根据不同类型特化
返回类型或特征。其设计似乎和 smart pointer,Value 派生类体系有关,因此需要在后面看到
它们的时候,再进一步进行分析学习。

转载于:https://my.oschina.net/u/232554/blog/41430

LLVM开发中,正确地使用类型检查和转换的工具,如isa<>、cast<>和dyn_cast<>,对于编写类型安全且高效的代码至关重要。要正确理解并运用这些工具,首先需要阅读《LLVM开发者指南:API详解与实用数据结构》,这份资料提供了对LLVM API和数据结构的深入理解,特别适合开发者在解决类型转换问题时参考。 参考资源链接:[LLVM开发者指南:API详解与实用数据结构](https://wenku.youkuaiyun.com/doc/648760vg1b?spm=1055.2569.3001.10343) 在实际的编程实践中,isa<>、cast<>和dyn_cast<>各自有不同的使用场景和优势: 1. **isa<>()**:这是一个模板函数,用于在编译时检查一个对象是否可以视为某类类型。isa<>是一种类型检查方式,用于确定一个对象是否可以安全地转换为特定类型,但不进行实际的转换。isa<>通常用于条件语句中,以判断对象类型。 2. **cast<>()**:cast<>模板用于在编译时执行静态类型转换。当确定一个对象可以安全地转换为目标类型时,使用cast<>进行转换。cast<>是一个编译时安全检查,它会在编译时验证类型转换的有效性。 3. **dyn_cast<>()**:与cast<>类似,dyn_cast<>也是用于类型转换,但它在运行时进行类型检查。当一个对象可能属于多种类型,且在运行时才能确定其确切类型时,使用dyn_cast<>进行动态类型转换是非常有用的。dyn_cast<>会对转换失败的情况进行处理,比如返回空指针(对于指针类型)或抛出异常(对于引用类型),从而提供类型安全的转换。 示例代码: ```cpp class Base { /* ... */ }; class Derived : public Base { /* ... */ }; void process(Base *Obj) { if (isa<Derived>(Obj)) { // 如果Obj确实是一个Derived类型的指针,isa<> 返回true Derived *DerivedObj = cast<Derived>(Obj); // cast<> 会安全地转换Obj到Derived*,但若Obj不是Derived类型,会导致编译错误 // ... 使用DerivedObj进行操作 } } void processWithRuntimeCheck(Base *Obj) { Derived *DerivedObj = dyn_cast<Derived>(Obj); // 如果Obj是一个Derived类型的指针,dyn_cast<> 将返回该指针;否则,返回nullptr if (DerivedObj) { // ... 使用DerivedObj进行操作 } else { // 处理Obj不是Derived类型的情况 } } ``` 在上述代码中,我们使用isa<>进行类型检查,cast<>进行静态类型转换,而dyn_cast<>则用于运行时类型检查。这样的设计确保了代码的类型安全性和运行时的健壮性。 在选择合适的数据结构和工具进行类型转换时,建议开发者深入学习《LLVM开发者指南:API详解与实用数据结构》,这不仅涵盖了类型转换的细节,还提供了关于LLVM中其他重要概念的全面信息。完成当前问题的解决后,这份资料将是你继续深化LLVM开发知识和技能的强大助手。 参考资源链接:[LLVM开发者指南:API详解与实用数据结构](https://wenku.youkuaiyun.com/doc/648760vg1b?spm=1055.2569.3001.10343)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值