如何LLVM isa<>实施? [英] How is LLVM isa<> implemented?

查看:162
本文介绍了如何LLVM isa<>实施?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

http://llvm.org/docs/CodingStandards.html#ci_rtti_exceptions

$ LLVM确实大量使用
RTTI的手动滚动形式,它使用
模板,如isa<>,cast<>和
dyn_cast<> ;.这种形式的RTTI是
opt-in,可以添加到任何类。
它也比dynamic_cast<>有效得多


isa和其他实现如何?

解决方案

首先,LLVM系统是非常特殊的,完全不是RTTI系统的替代。 / p>

房屋




  • 不需要生成RTTI信息

  • 当需要时,信息只在给定的层次结构中有意义

  • 我们排除了从此系统的多继承



标识对象类



简单的层次结构,例如:

  struct Base {}; / * abstract * / 
struct DerivedLeft:Base {}; / * abstract * /
struct DerivedRight:Base {};
struct MostDerivedL1:DerivedLeft {};
struct MostDerivedL2:DerivedLeft {};
struct MostDerivedR:DerivedRight {};

我们将使用枚举成员创建特定于此层次结构的枚举

 枚举BaseId {
DerivedRightId ,
MostDerivedL1Id,
MostDerivedL2Id,
MostDerivedRId
};

然后, Base

  struct Base {
static inline bool classof(Base const *){ return true; }

Base(BaseId id):Id(id){}

BaseId getValueID()const {return Id; }

BaseId Id;
};

并且每个具体类也以此方式增强:

  struct DerivedRight:Base {
static inline bool classof(DerivedRight const *){return true; }

static inline bool classof(Base const * B){
switch(B-> getValueID()){
case DerivedRightId:case MostDerivedRId:return true;
default:return false;
}
}

DerivedRight(BaseId id = DerivedRightId):Base(id){}
};

现在,只要查询确切类型,就可以进行投射。



隐藏实施细节

让用户使用 getValueID 将是麻烦的,所以在LLVM中使用 classof 方法隐藏。



给定类应该实现两个 classof 方法:一个用于其最深的基础(测试 BaseId )和一个自身(纯优化)。例如:

  struct MostDerivedL1:DerivedLeft {
static inline bool classof(MostDerivedL1 const *){return true; }

static inline bool classof(Base const * B){
return B-> getValueID()== MostDerivedL1Id;
}

MostDerivedL1():DerivedLeft(MostDerivedL1Id){}
};这样,我们可以通过模板检查是否可以转换:



 模板< typename To,typename From> 
bool isa(from const& f){
return To :: classof(& f);
}

想象一会儿 MostDerivedL1




  • if / code>是 MostDerivedL1 ,那么我们调用 classof 的第一个重载, >
  • 如果是任何其他的,那么我们调用 classof 的第二个重载,该检查使用枚举来确定具体类型是否匹配。



希望它更清楚。


From http://llvm.org/docs/CodingStandards.html#ci_rtti_exceptions

LLVM does make extensive use of a hand-rolled form of RTTI that use templates like isa<>, cast<>, and dyn_cast<>. This form of RTTI is opt-in and can be added to any class. It is also substantially more efficient than dynamic_cast<>.

How is isa and the others implemented?

解决方案

First of all, the LLVM system is extremely specific and not at all a drop-in replacement for the RTTI system.

Premises

  • For most classes, it is unnecessary to generate RTTI information
  • When it is required, the information only makes sense within a given hierarchy
  • We preclude multi-inheritance from this system

Identifying an object class

Take a simple hierarchy, for example:

struct Base {}; /* abstract */
struct DerivedLeft: Base {}; /* abstract */
struct DerivedRight:Base {};
struct MostDerivedL1: DerivedLeft {};
struct MostDerivedL2: DerivedLeft {};
struct MostDerivedR: DerivedRight {};

We will create an enum specific to this hierarchy, with an enum member for each of the hierarchy member that can be instantiated (the others would be useless).

enum BaseId {
  DerivedRightId,
  MostDerivedL1Id,
  MostDerivedL2Id,
  MostDerivedRId
};

Then, the Base class will be augmented with a method that will return this enum.

struct Base {
  static inline bool classof(Base const*) { return true; }

  Base(BaseId id): Id(id) {}

  BaseId getValueID() const { return Id; }

  BaseId Id;
};

And each concrete class is augmented too, in this manner:

struct DerivedRight: Base {
  static inline bool classof(DerivedRight const*) { return true; }

  static inline bool classof(Base const* B) {
    switch(B->getValueID()) {
    case DerivedRightId: case MostDerivedRId: return true;
    default: return false;
    }
  }

  DerivedRight(BaseId id = DerivedRightId): Base(id) {}
};

Now, it is possible, simply, to query the exact type, for casting.

Hiding implementation details

Having the users murking with getValueID would be troublesome though, so in LLVM this is hidden with the use of classof methods.

A given class should implement two classof methods: one for its deepest base (with a test of the suitable values of BaseId) and one for itself (pure optimization). For example:

struct MostDerivedL1: DerivedLeft {
  static inline bool classof(MostDerivedL1 const*) { return true; }

  static inline bool classof(Base const* B) {
    return B->getValueID() == MostDerivedL1Id;
  }

  MostDerivedL1(): DerivedLeft(MostDerivedL1Id) {}
};

This way, we can check whether a cast is possible or not through the templates:

template <typename To, typename From>
bool isa(From const& f) {
  return To::classof(&f);
}

Imagine for a moment that To is MostDerivedL1:

  • if From is MostDerivedL1, then we invoke the first overload of classof, and it works
  • if From is anything other, then we invoke the second overload of classof, and the check uses the enum to determine if the concrete type match.

Hope it's clearer.

这篇关于如何LLVM isa&lt;&gt;实施?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆