verilator/src/V3Rtti.h

132 lines
5.2 KiB
C++

// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
// DESCRIPTION: Verilator: Simple and efficient Run-Time Type Information
//
// Code available from: https://verilator.org
//
//*************************************************************************
//
// Copyright 2003-2025 by Wilson Snyder. This program is free software; you
// can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
//
//*************************************************************************
#ifndef VERILATOR_V3RTTI_H_
#define VERILATOR_V3RTTI_H_
#include "verilatedos.h"
#include <cstdint>
#include <type_traits>
// Holds list of types as template parameter pack.
// Useful in compile-time code generation.
template <typename... TN>
struct VTypeList final {
template <typename... UN>
constexpr VTypeList<TN..., UN...> operator+(VTypeList<UN...>) const {
return {};
}
};
// Holds one type.
// Can be safely used as a return or argument type, and even instantiated, without triggering any
// potential limitations or effects of the held type.
template <typename T>
struct VTypeWrapper final {
using type_t = T;
};
// Implementation details of other constructs defined in this header.
namespace V3RttiInternal {
// Helper function for extracting first type from VTypeList.
template <typename T0, typename... TN>
static inline constexpr VTypeWrapper<T0> vlTypeListFront(VTypeList<T0, TN...>) {
return {};
}
// Overload for empty type list. Returns false.
inline static constexpr bool isClassIdOfOneOf(uintptr_t id, VTypeList<>) VL_PURE { return false; }
// Returns true iff `id` has the same value as `T::rttiClassId()`, where `T` is any type held by
// `VTypeList` object passed as the second argument.
template <typename Base0, typename... BaseN>
inline static constexpr bool isClassIdOfOneOf(uintptr_t id, VTypeList<Base0, BaseN...>) VL_PURE {
return id == Base0::rttiClassId() || isClassIdOfOneOf(id, VTypeList<BaseN...>{});
}
} // namespace V3RttiInternal
// Alias for the first (frontmost) type held by type list `TL`.
template <typename TL>
using VTypeListFront = typename decltype(::V3RttiInternal::vlTypeListFront(TL{}))::type_t;
// `VTypeList` holding types from type lists `TL1` followed by types from type list `TL2`.
template <typename TL1, typename TL2>
using VJoinedTypeLists = decltype(TL1{} + TL2{});
// Common code used by VL_RTTI_COMMON_IMPL and VL_RTTI_COMMON_IMPL_BASE.
#define V3RTTIINTERNAL_VL_RTTI_COMMON_IMPL(ThisClass) \
private: \
/* A type used only for implementation of the static_assert below. */ \
struct RttiUniqueTypeForThisClass {}; \
static_assert( \
std::is_same<RttiUniqueTypeForThisClass, ThisClass::RttiUniqueTypeForThisClass>::value, \
"'ThisClass' argument (" #ThisClass ") does not match the class name"); \
\
public: \
/* Returns unique ID of the class. Useful with `isInstanceOfClassWithId()` method. */ \
static uintptr_t rttiClassId() VL_PURE { \
/* The only purpose of the following variable is to occupy an unique memory address. */ \
/* This address is used as an unique class ID. */ \
static char aStaticVariable; \
return reinterpret_cast<uintptr_t>(&aStaticVariable); \
}
// Call this macro at the beginning of class definition if the class derives from a
// class with VL_RTTI_IMPL or VL_RTTI_IMPL_BASE calls.
#define VL_RTTI_IMPL(ThisClass, DirectBaseClass) \
V3RTTIINTERNAL_VL_RTTI_COMMON_IMPL(ThisClass) \
static_assert( \
std::is_same<DirectBaseClass, \
VTypeListFront<DirectBaseClass::RttiThisAndBaseClassesList>>::value, \
"Missing VL_RTTI_IMPL(...) in the direct base class (" #DirectBaseClass ")"); \
\
public: \
/* Type list containing this class and all classes from the inheritance chain. */ \
using RttiThisAndBaseClassesList \
= VJoinedTypeLists<VTypeList<ThisClass>, \
typename DirectBaseClass::RttiThisAndBaseClassesList>; \
\
protected: \
/* Returns true iff `id` has the same value as `T::rttiClassId()`, where `T` is either this \
* class or any class from this class' inheritance chain. */ \
bool isInstanceOfClassWithId(uintptr_t id) const override VL_PURE { \
return ::V3RttiInternal::isClassIdOfOneOf(id, RttiThisAndBaseClassesList{}); \
} \
\
private: /* Revert to private visibility after this macro */
// Call this macro at the beginning of a base class to implement class type queries using
// `p->isInstanceOfClassWithId(ClassName::rttiClassId())`.
#define VL_RTTI_IMPL_BASE(ThisClass) \
V3RTTIINTERNAL_VL_RTTI_COMMON_IMPL(ThisClass) \
public: \
/* Type list containing this class and all classes from the inheritance chain. */ \
using RttiThisAndBaseClassesList = VTypeList<ThisClass>; \
\
protected: \
/* Returns true iff `id` has the same value as value returned by this class' \
`rttiClassId()` method. */ \
virtual bool isInstanceOfClassWithId(uintptr_t id) const VL_PURE { \
return id == rttiClassId(); \
} \
\
private: /* Revert to private visibility after this macro */
#endif // Guard