LLVM InstVisitor - 没有虚拟功能?

LLVM InstVisitor - No Virtual Functions?

我一直在查看他们实现访客模式的 LLVM InstVisitor.h 文件。它们的实现与我在访问者模式中看到的任何东西都大不相同。

在文档中我发现了这个:

To define your own visitor, inherit from this class, specifying your new type for the 'SubClass' template parameter, and "override" visitXXX functions in your class. I say "override" because this class is defined in terms of statically resolved overloading, not virtual functions.

...

Note that this class is specifically designed as a template to avoid virtual function call overhead. Defining and using an InstVisitor is just as efficient as having your own switch statement over the instruction opcode.

我问是因为 说 LLVM 在此实现中使用了访问者模式,但我无法弄清楚为什么它与我见过的任何其他实现如此不同。

文件中的访问者模式是如何使用的?

llvm::InstVisitor 使用 Curiously Recurring Template Pattern (CRTP),这是一种用于执行访问成员函数静态分派的 C++ 习惯用法。

这样,正确的 visitXXX 调用将被静态解析(在编译时),避免了动态虚拟调用解析的额外成本。

这是通过调用这样的东西来工作的:

// The compiler will choose the Derived implementation of visitXXX
// if exists, but will fallback to the Base implementation as Derived 
// inherits from Base. All done at compile time.
void Base::do_visit() {
  return static_cast<Derived *>(this)->visitXXX();
}

请注意,没有类似 "override" 的机制:如果您无法为一次访问函数匹配确切的函数签名,它将调用基础 class 实现,而不是您自己的实现。

用法示例与文档中解释的完全相同:

struct CountAllocaVisitor : public InstVisitor<CountAllocaVisitor> {
  unsigned Count;
  CountAllocaVisitor() : Count(0) {}
  void visitAllocaInst(AllocaInst &AI) { ++Count; }
};

// And this class would be used like this:
CountAllocaVisitor CAV;
CAV.visit(function);
NumAllocas = CAV.Count;