[llvm-dev] RFC: virtual-like methods via LLVM-style RTTI
David Zarzycki via llvm-dev
llvm-dev at lists.llvm.org
Thu May 3 14:09:05 PDT 2018
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
More information about the llvm-dev
mailing list