[llvm-dev] RFC: virtual-like methods via LLVM-style RTTI

Reid Kleckner via llvm-dev llvm-dev at lists.llvm.org
Thu May 10 15:21:16 PDT 2018


If you can use this to clean up things like Value::deleteValue, that would
be amazing. Go for it. :)

On Thu, May 3, 2018 at 2:09 PM David Zarzycki via llvm-dev <
llvm-dev at lists.llvm.org> wrote:

> Hello,
>
> 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.
>
> Thanks,
> Dave
>
>
>
>
> //===- llvm/Support/VTable.h - LLVM-style vtables ---------------*- C++
> -*-===//
> //
> //                     The LLVM Compiler Infrastructure
> //
> // This file is distributed under the University of Illinois Open Source
> // License. See LICENSE.TXT for details.
> //
>
> //===----------------------------------------------------------------------===//
> //
> // This file provides LLVM_VIRTUAL() and related macros for creating
> virtual
> // methods that demultiplex via LLVM-style RTTI.
> //
>
> //===----------------------------------------------------------------------===//
>
> #ifndef LLVM_SUPPORT_VTABLE_H
> #define LLVM_SUPPORT_VTABLE_H
>
> #include <functional>
>
> namespace llvm {
>
>
> //===----------------------------------------------------------------------===//
> //                   LLVM-style VTable Support macros
>
> //===----------------------------------------------------------------------===//
>
> // Virtual method dispatch via LLVM runtime type information. This approach
> // requires a little bit more work than native C++ 'virtual' methods, but
> the
> // memory savings can be well worth it. On non-PIC x86 systems, the same
> // number of instructions are generated. On PIC x86 systems, one additional
> // instruction is generated to compute (or load) the pointer to the vtable
> // (LEA or MOV respectively), and the compiler is smart enough to hoist the
> // LEA/MOV outside of loops and cache the result.
> //
> // For subclasses, virtual methods are declared like so:
> //
> //   LLVM_VIRTUAL_THUNK(BaseTy, makeSound)
> //   void LLVM_VIRTUAL(makeSound)(int howLoud) { /* normal body */ }
> //
> // For base classes, one must do a little more work. The simplest case is
> an
> // abstract virtual method in a type called 'Base':
> //
> //   void LLVM_ABSTRACT_VIRTUAL(BaseTy, makeSound)
> //
> // And then later in the header file, the vtable definition:
> //
> // LLVM_ABSTRACT_VIRTUAL_BEGIN(BaseTy, makeSound)
> // #define BASE_NODE(Ty, ...) LLVM_ABSTRACT_VIRTUAL_SLOT(Ty, makeSound)
> // #include <BaseTy.inc>
> // LLVM_ABSTRACT_VIRTUAL_END(getKind())
> //
> //
> // Example:
> //
> // class Cat {
> //   ...
> //
> //   void LLVM_ABSTRACT_VIRTUAL(Base, makeSound)
> //
> //   LLVM_BASE_VIRTUAL(Base, getOffspringCount)
> //   size_t LLVM_VIRTUAL(getOffspringCount)() const {
> //     return 0;
> //   }
> // };
> //
> //
> // class Lion : public Cat {
> //   ...
> //
> //   LLVM_VIRTUAL_THUNK(Base, makeSound)
> //   void LLVM_VIRTUAL(makeSound)() {
> //     ...
> //   }
> //
> //   LLVM_VIRTUAL_THUNK(Base, getOffspringCount)
> //   size_t LLVM_VIRTUAL(getOffspringCount)() const {
> //     ...
> //   }
> // };
>
>
> #define LLVM_VIRTUAL_THUNK(Ty, BaseTy, Method) \
>   template <typename... Args> \
>   static auto _virtual_##Method(BaseTy *b, Args... args) -> auto { \
>     return static_cast<Ty*>(b) \
>       ->_virtualbody_##Method(std::forward<Args>(args)...); \
>   }
>
> #define LLVM_VIRTUAL(Method) \
>   __attribute__((always_inline)) _virtualbody_##Method
>
> #define LLVM_ABSTRACT_VIRTUAL(BaseTy, Method) \
>   __attribute__((noreturn)) \
>   LLVM_VIRTUAL(Method)(...) { \
>     llvm_unreachable("Unhandled LLVM-virtual method"); \
>   } \
>   template <typename... Args> \
>   auto Method(Args... args) -> auto; \
>   LLVM_VIRTUAL_THUNK(BaseTy, BaseTy, Method)
>
> #define LLVM_BASE_VIRTUAL(BaseTy, Method) \
>   template <typename... Args> \
>   auto Method(Args... args) -> auto; \
>   LLVM_VIRTUAL_THUNK(BaseTy, BaseTy, Method)
>
> #define LLVM_ABSTRACT_VIRTUAL_BEGIN(BaseTy, Method) \
>   template <typename... Args> \
>   auto BaseTy::Method(Args... args) -> auto { \
>     static const decltype(&BaseTy::_virtual_##Method<Args...>) vtable[] = {
>
> #define LLVM_ABSTRACT_VIRTUAL_SLOT(Ty, Method) \
>       &Ty::_virtual_##Method<Args...>,
>
> #define LLVM_ABSTRACT_VIRTUAL_END(GetKind) \
>     }; \
>     return vtable[GetKind](this, std::forward<Args>(args)...); \
>   }
>
> } // end namespace llvm
>
> #endif // LLVM_SUPPORT_VTABLE_H
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180510/02237f9a/attachment.html>


More information about the llvm-dev mailing list