<div dir="ltr">If you can use this to clean up things like Value::deleteValue, that would be amazing. Go for it. :)</div><br><div class="gmail_quote"><div dir="ltr">On Thu, May 3, 2018 at 2:09 PM David Zarzycki via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello,<br>
<br>
In an effort to help LLVM-style projects save memory, I’ve been toying with some macros that provide an alternative to C++ vtables that use LLVM-style RTTI design patterns instead. Is this something that LLVM or sub-projects think is worth pursuing? Or are the macros below too ugly/problematic? Feedback would be appreciated.<br>
<br>
Thanks,<br>
Dave<br>
<br>
<br>
<br>
<br>
//===- llvm/Support/VTable.h - LLVM-style vtables ---------------*- C++ -*-===//<br>
//<br>
//                     The LLVM Compiler Infrastructure<br>
//<br>
// This file is distributed under the University of Illinois Open Source<br>
// License. See LICENSE.TXT for details.<br>
//<br>
//===----------------------------------------------------------------------===//<br>
//<br>
// This file provides LLVM_VIRTUAL() and related macros for creating virtual<br>
// methods that demultiplex via LLVM-style RTTI.<br>
//<br>
//===----------------------------------------------------------------------===//<br>
<br>
#ifndef LLVM_SUPPORT_VTABLE_H<br>
#define LLVM_SUPPORT_VTABLE_H<br>
<br>
#include <functional><br>
<br>
namespace llvm {<br>
<br>
//===----------------------------------------------------------------------===//<br>
//                   LLVM-style VTable Support macros<br>
//===----------------------------------------------------------------------===//<br>
<br>
// Virtual method dispatch via LLVM runtime type information. This approach<br>
// requires a little bit more work than native C++ 'virtual' methods, but the<br>
// memory savings can be well worth it. On non-PIC x86 systems, the same<br>
// number of instructions are generated. On PIC x86 systems, one additional<br>
// instruction is generated to compute (or load) the pointer to the vtable<br>
// (LEA or MOV respectively), and the compiler is smart enough to hoist the<br>
// LEA/MOV outside of loops and cache the result.<br>
//<br>
// For subclasses, virtual methods are declared like so:<br>
//<br>
//   LLVM_VIRTUAL_THUNK(BaseTy, makeSound)<br>
//   void LLVM_VIRTUAL(makeSound)(int howLoud) { /* normal body */ }<br>
//<br>
// For base classes, one must do a little more work. The simplest case is an<br>
// abstract virtual method in a type called 'Base':<br>
//<br>
//   void LLVM_ABSTRACT_VIRTUAL(BaseTy, makeSound)<br>
//<br>
// And then later in the header file, the vtable definition:<br>
//<br>
// LLVM_ABSTRACT_VIRTUAL_BEGIN(BaseTy, makeSound)<br>
// #define BASE_NODE(Ty, ...) LLVM_ABSTRACT_VIRTUAL_SLOT(Ty, makeSound)<br>
// #include <BaseTy.inc><br>
// LLVM_ABSTRACT_VIRTUAL_END(getKind())<br>
//<br>
//<br>
// Example:<br>
//<br>
// class Cat {<br>
//   ...<br>
//<br>
//   void LLVM_ABSTRACT_VIRTUAL(Base, makeSound)<br>
//<br>
//   LLVM_BASE_VIRTUAL(Base, getOffspringCount)<br>
//   size_t LLVM_VIRTUAL(getOffspringCount)() const {<br>
//     return 0;<br>
//   }<br>
// };<br>
//<br>
//<br>
// class Lion : public Cat {<br>
//   ...<br>
//<br>
//   LLVM_VIRTUAL_THUNK(Base, makeSound)<br>
//   void LLVM_VIRTUAL(makeSound)() {<br>
//     ...<br>
//   }<br>
//<br>
//   LLVM_VIRTUAL_THUNK(Base, getOffspringCount)<br>
//   size_t LLVM_VIRTUAL(getOffspringCount)() const {<br>
//     ...<br>
//   }<br>
// };<br>
<br>
<br>
#define LLVM_VIRTUAL_THUNK(Ty, BaseTy, Method) \<br>
  template <typename... Args> \<br>
  static auto _virtual_##Method(BaseTy *b, Args... args) -> auto { \<br>
    return static_cast<Ty*>(b) \<br>
      ->_virtualbody_##Method(std::forward<Args>(args)...); \<br>
  }<br>
<br>
#define LLVM_VIRTUAL(Method) \<br>
  __attribute__((always_inline)) _virtualbody_##Method<br>
<br>
#define LLVM_ABSTRACT_VIRTUAL(BaseTy, Method) \<br>
  __attribute__((noreturn)) \<br>
  LLVM_VIRTUAL(Method)(...) { \<br>
    llvm_unreachable("Unhandled LLVM-virtual method"); \<br>
  } \<br>
  template <typename... Args> \<br>
  auto Method(Args... args) -> auto; \<br>
  LLVM_VIRTUAL_THUNK(BaseTy, BaseTy, Method)<br>
<br>
#define LLVM_BASE_VIRTUAL(BaseTy, Method) \<br>
  template <typename... Args> \<br>
  auto Method(Args... args) -> auto; \<br>
  LLVM_VIRTUAL_THUNK(BaseTy, BaseTy, Method)<br>
<br>
#define LLVM_ABSTRACT_VIRTUAL_BEGIN(BaseTy, Method) \<br>
  template <typename... Args> \<br>
  auto BaseTy::Method(Args... args) -> auto { \<br>
    static const decltype(&BaseTy::_virtual_##Method<Args...>) vtable[] = {<br>
<br>
#define LLVM_ABSTRACT_VIRTUAL_SLOT(Ty, Method) \<br>
      &Ty::_virtual_##Method<Args...>,<br>
<br>
#define LLVM_ABSTRACT_VIRTUAL_END(GetKind) \<br>
    }; \<br>
    return vtable[GetKind](this, std::forward<Args>(args)...); \<br>
  }<br>
<br>
} // end namespace llvm<br>
<br>
#endif // LLVM_SUPPORT_VTABLE_H<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div>