[clang] [clang][NFC] Create CodeGenShared component for shared code with ClangIR (PR #157936)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 21 10:59:17 PDT 2025
https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/157936
>From 30ffdaddbf3d082a305d98c6ac01effd38418f39 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Tue, 9 Sep 2025 20:37:27 +0200
Subject: [PATCH] [clang][NFC] Create CodeGenShared component for shared code
with ClangIR
---
.../clang/CodeGenShared/ItaniumRTTIBuilder.h | 117 +++++
clang/lib/CMakeLists.txt | 1 +
clang/lib/CodeGen/CMakeLists.txt | 1 +
clang/lib/CodeGen/ItaniumCXXABI.cpp | 473 +-----------------
clang/lib/CodeGenShared/CMakeLists.txt | 11 +
.../lib/CodeGenShared/ItaniumRTTIBuilder.cpp | 418 ++++++++++++++++
6 files changed, 553 insertions(+), 468 deletions(-)
create mode 100644 clang/include/clang/CodeGenShared/ItaniumRTTIBuilder.h
create mode 100644 clang/lib/CodeGenShared/CMakeLists.txt
create mode 100644 clang/lib/CodeGenShared/ItaniumRTTIBuilder.cpp
diff --git a/clang/include/clang/CodeGenShared/ItaniumRTTIBuilder.h b/clang/include/clang/CodeGenShared/ItaniumRTTIBuilder.h
new file mode 100644
index 0000000000000..0db0618d279d0
--- /dev/null
+++ b/clang/include/clang/CodeGenShared/ItaniumRTTIBuilder.h
@@ -0,0 +1,117 @@
+//===--- ItaniumRTTIBuilder.h - LLVM Backend Utilities ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGENSHARED_ITANIUMRTTIBUILDER_H
+#define LLVM_CLANG_LIB_CODEGENSHARED_ITANIUMRTTIBUILDER_H
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/TypeBase.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+namespace clang {
+
+namespace CodeGenShared {
+
+// Pointer type info flags.
+enum {
+ /// PTI_Const - Type has const qualifier.
+ PTI_Const = 0x1,
+
+ /// PTI_Volatile - Type has volatile qualifier.
+ PTI_Volatile = 0x2,
+
+ /// PTI_Restrict - Type has restrict qualifier.
+ PTI_Restrict = 0x4,
+
+ /// PTI_Incomplete - Type is incomplete.
+ PTI_Incomplete = 0x8,
+
+ /// PTI_ContainingClassIncomplete - Containing class is incomplete.
+ /// (in pointer to member).
+ PTI_ContainingClassIncomplete = 0x10,
+
+ /// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).
+ // PTI_TransactionSafe = 0x20,
+
+ /// PTI_Noexcept - Pointee is noexcept function (C++1z).
+ PTI_Noexcept = 0x40,
+};
+
+// VMI type info flags.
+enum {
+ /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
+ VMI_NonDiamondRepeat = 0x1,
+
+ /// VMI_DiamondShaped - Class is diamond shaped.
+ VMI_DiamondShaped = 0x2
+};
+
+// Base class type info flags.
+enum {
+ /// BCTI_Virtual - Base class is virtual.
+ BCTI_Virtual = 0x1,
+
+ /// BCTI_Public - Base class is public.
+ BCTI_Public = 0x2
+};
+
+/// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type
+/// info for that type is defined in the standard library.
+bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty);
+
+bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy);
+
+/// IsStandardLibraryRTTIDescriptor - Returns whether the type
+/// information for the given type exists in the standard library.
+bool IsStandardLibraryRTTIDescriptor(QualType Ty);
+
+/// IsIncompleteClassType - Returns whether the given record type is incomplete.
+bool IsIncompleteClassType(const RecordType *RecordTy);
+
+/// ContainsIncompleteClassType - Returns whether the given type contains an
+/// incomplete class type. This is true if
+///
+/// * The given type is an incomplete class type.
+/// * The given type is a pointer type whose pointee type contains an
+/// incomplete class type.
+/// * The given type is a member pointer type whose class is an incomplete
+/// class type.
+/// * The given type is a member pointer type whoise pointee type contains an
+/// incomplete class type.
+/// is an indirect or direct pointer to an incomplete class type.
+bool ContainsIncompleteClassType(QualType Ty);
+
+// CanUseSingleInheritance - Return whether the given record decl has a "single,
+// public, non-virtual base at offset zero (i.e. the derived class is dynamic
+// iff the base is)", according to Itanium C++ ABI, 2.95p6b.
+bool CanUseSingleInheritance(const CXXRecordDecl *RD);
+
+const char *VTableClassNameForType(const Type *Ty);
+
+/// Compute the flags for a __pbase_type_info, and remove the corresponding
+/// pieces from \p Type.
+unsigned extractPBaseFlags(ASTContext &Ctx, QualType &Type);
+
+/// SeenBases - Contains virtual and non-virtual bases seen when traversing
+/// a class hierarchy.
+struct SeenBases {
+ llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
+ llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
+};
+
+/// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in
+/// abi::__vmi_class_type_info.
+unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
+ SeenBases &Bases);
+
+unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD);
+
+} // namespace CodeGenShared
+} // namespace clang
+
+#endif
diff --git a/clang/lib/CMakeLists.txt b/clang/lib/CMakeLists.txt
index 4f2218b583e41..5032c80943385 100644
--- a/clang/lib/CMakeLists.txt
+++ b/clang/lib/CMakeLists.txt
@@ -8,6 +8,7 @@ add_subdirectory(ASTMatchers)
add_subdirectory(CrossTU)
add_subdirectory(Sema)
add_subdirectory(CodeGen)
+add_subdirectory(CodeGenShared)
add_subdirectory(Analysis)
add_subdirectory(Edit)
add_subdirectory(ExtractAPI)
diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index ad9ef91c781a8..9672cfac82c85 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -168,6 +168,7 @@ add_clang_library(clangCodeGen
clangAST
clangAnalysis
clangBasic
+ clangCodeGenShared
clangFrontend
clangLex
clangSerialization
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 7dc2eaf1e9f75..1b618532a379e 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -28,8 +28,8 @@
#include "clang/AST/Attr.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/StmtCXX.h"
-#include "clang/AST/Type.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
+#include "clang/CodeGenShared/ItaniumRTTIBuilder.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Instructions.h"
@@ -41,6 +41,7 @@
using namespace clang;
using namespace CodeGen;
+using namespace CodeGenShared;
namespace {
class ItaniumCXXABI : public CodeGen::CGCXXABI {
@@ -3544,49 +3545,6 @@ class ItaniumRTTIBuilder {
ItaniumRTTIBuilder(const ItaniumCXXABI &ABI)
: CGM(ABI.CGM), VMContext(CGM.getModule().getContext()), CXXABI(ABI) {}
- // Pointer type info flags.
- enum {
- /// PTI_Const - Type has const qualifier.
- PTI_Const = 0x1,
-
- /// PTI_Volatile - Type has volatile qualifier.
- PTI_Volatile = 0x2,
-
- /// PTI_Restrict - Type has restrict qualifier.
- PTI_Restrict = 0x4,
-
- /// PTI_Incomplete - Type is incomplete.
- PTI_Incomplete = 0x8,
-
- /// PTI_ContainingClassIncomplete - Containing class is incomplete.
- /// (in pointer to member).
- PTI_ContainingClassIncomplete = 0x10,
-
- /// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).
- //PTI_TransactionSafe = 0x20,
-
- /// PTI_Noexcept - Pointee is noexcept function (C++1z).
- PTI_Noexcept = 0x40,
- };
-
- // VMI type info flags.
- enum {
- /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
- VMI_NonDiamondRepeat = 0x1,
-
- /// VMI_DiamondShaped - Class is diamond shaped.
- VMI_DiamondShaped = 0x2
- };
-
- // Base class type info flags.
- enum {
- /// BCTI_Virtual - Base class is virtual.
- BCTI_Virtual = 0x1,
-
- /// BCTI_Public - Base class is public.
- BCTI_Public = 0x2
- };
-
/// BuildTypeInfo - Build the RTTI type info struct for the given type, or
/// link to an existing RTTI descriptor if one already exists.
llvm::Constant *BuildTypeInfo(QualType Ty);
@@ -3598,7 +3556,7 @@ class ItaniumRTTIBuilder {
llvm::GlobalValue::VisibilityTypes Visibility,
llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);
};
-}
+} // namespace
llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(
QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage) {
@@ -3654,154 +3612,6 @@ ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
return GV;
}
-/// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type
-/// info for that type is defined in the standard library.
-static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
- // Itanium C++ ABI 2.9.2:
- // Basic type information (e.g. for "int", "bool", etc.) will be kept in
- // the run-time support library. Specifically, the run-time support
- // library should contain type_info objects for the types X, X* and
- // X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char,
- // unsigned char, signed char, short, unsigned short, int, unsigned int,
- // long, unsigned long, long long, unsigned long long, float, double,
- // long double, char16_t, char32_t, and the IEEE 754r decimal and
- // half-precision floating point types.
- //
- // GCC also emits RTTI for __int128.
- // FIXME: We do not emit RTTI information for decimal types here.
-
- // Types added here must also be added to EmitFundamentalRTTIDescriptors.
- switch (Ty->getKind()) {
- case BuiltinType::Void:
- case BuiltinType::NullPtr:
- case BuiltinType::Bool:
- case BuiltinType::WChar_S:
- case BuiltinType::WChar_U:
- case BuiltinType::Char_U:
- case BuiltinType::Char_S:
- case BuiltinType::UChar:
- case BuiltinType::SChar:
- case BuiltinType::Short:
- case BuiltinType::UShort:
- case BuiltinType::Int:
- case BuiltinType::UInt:
- case BuiltinType::Long:
- case BuiltinType::ULong:
- case BuiltinType::LongLong:
- case BuiltinType::ULongLong:
- case BuiltinType::Half:
- case BuiltinType::Float:
- case BuiltinType::Double:
- case BuiltinType::LongDouble:
- case BuiltinType::Float16:
- case BuiltinType::Float128:
- case BuiltinType::Ibm128:
- case BuiltinType::Char8:
- case BuiltinType::Char16:
- case BuiltinType::Char32:
- case BuiltinType::Int128:
- case BuiltinType::UInt128:
- return true;
-
-#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
- case BuiltinType::Id:
-#include "clang/Basic/OpenCLImageTypes.def"
-#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
- case BuiltinType::Id:
-#include "clang/Basic/OpenCLExtensionTypes.def"
- case BuiltinType::OCLSampler:
- case BuiltinType::OCLEvent:
- case BuiltinType::OCLClkEvent:
- case BuiltinType::OCLQueue:
- case BuiltinType::OCLReserveID:
-#define SVE_TYPE(Name, Id, SingletonId) \
- case BuiltinType::Id:
-#include "clang/Basic/AArch64ACLETypes.def"
-#define PPC_VECTOR_TYPE(Name, Id, Size) \
- case BuiltinType::Id:
-#include "clang/Basic/PPCTypes.def"
-#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
-#include "clang/Basic/RISCVVTypes.def"
-#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
-#include "clang/Basic/WebAssemblyReferenceTypes.def"
-#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
-#include "clang/Basic/AMDGPUTypes.def"
-#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
-#include "clang/Basic/HLSLIntangibleTypes.def"
- case BuiltinType::ShortAccum:
- case BuiltinType::Accum:
- case BuiltinType::LongAccum:
- case BuiltinType::UShortAccum:
- case BuiltinType::UAccum:
- case BuiltinType::ULongAccum:
- case BuiltinType::ShortFract:
- case BuiltinType::Fract:
- case BuiltinType::LongFract:
- case BuiltinType::UShortFract:
- case BuiltinType::UFract:
- case BuiltinType::ULongFract:
- case BuiltinType::SatShortAccum:
- case BuiltinType::SatAccum:
- case BuiltinType::SatLongAccum:
- case BuiltinType::SatUShortAccum:
- case BuiltinType::SatUAccum:
- case BuiltinType::SatULongAccum:
- case BuiltinType::SatShortFract:
- case BuiltinType::SatFract:
- case BuiltinType::SatLongFract:
- case BuiltinType::SatUShortFract:
- case BuiltinType::SatUFract:
- case BuiltinType::SatULongFract:
- case BuiltinType::BFloat16:
- return false;
-
- case BuiltinType::Dependent:
-#define BUILTIN_TYPE(Id, SingletonId)
-#define PLACEHOLDER_TYPE(Id, SingletonId) \
- case BuiltinType::Id:
-#include "clang/AST/BuiltinTypes.def"
- llvm_unreachable("asking for RRTI for a placeholder type!");
-
- case BuiltinType::ObjCId:
- case BuiltinType::ObjCClass:
- case BuiltinType::ObjCSel:
- llvm_unreachable("FIXME: Objective-C types are unsupported!");
- }
-
- llvm_unreachable("Invalid BuiltinType Kind!");
-}
-
-static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) {
- QualType PointeeTy = PointerTy->getPointeeType();
- const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);
- if (!BuiltinTy)
- return false;
-
- // Check the qualifiers.
- Qualifiers Quals = PointeeTy.getQualifiers();
- Quals.removeConst();
-
- if (!Quals.empty())
- return false;
-
- return TypeInfoIsInStandardLibrary(BuiltinTy);
-}
-
-/// IsStandardLibraryRTTIDescriptor - Returns whether the type
-/// information for the given type exists in the standard library.
-static bool IsStandardLibraryRTTIDescriptor(QualType Ty) {
- // Type info for builtin types is defined in the standard library.
- if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
- return TypeInfoIsInStandardLibrary(BuiltinTy);
-
- // Type info for some pointer types to builtin types is defined in the
- // standard library.
- if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
- return TypeInfoIsInStandardLibrary(PointerTy);
-
- return false;
-}
-
/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
/// the given type exists somewhere else, and that we should not emit the type
/// information in this translation unit. Assumes that it is not a
@@ -3848,195 +3658,9 @@ static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM,
return false;
}
-/// IsIncompleteClassType - Returns whether the given record type is incomplete.
-static bool IsIncompleteClassType(const RecordType *RecordTy) {
- return !RecordTy->getOriginalDecl()
- ->getDefinitionOrSelf()
- ->isCompleteDefinition();
-}
-
-/// ContainsIncompleteClassType - Returns whether the given type contains an
-/// incomplete class type. This is true if
-///
-/// * The given type is an incomplete class type.
-/// * The given type is a pointer type whose pointee type contains an
-/// incomplete class type.
-/// * The given type is a member pointer type whose class is an incomplete
-/// class type.
-/// * The given type is a member pointer type whoise pointee type contains an
-/// incomplete class type.
-/// is an indirect or direct pointer to an incomplete class type.
-static bool ContainsIncompleteClassType(QualType Ty) {
- if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
- if (IsIncompleteClassType(RecordTy))
- return true;
- }
-
- if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
- return ContainsIncompleteClassType(PointerTy->getPointeeType());
-
- if (const MemberPointerType *MemberPointerTy =
- dyn_cast<MemberPointerType>(Ty)) {
- // Check if the class type is incomplete.
- if (!MemberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())
- return true;
-
- return ContainsIncompleteClassType(MemberPointerTy->getPointeeType());
- }
-
- return false;
-}
-
-// CanUseSingleInheritance - Return whether the given record decl has a "single,
-// public, non-virtual base at offset zero (i.e. the derived class is dynamic
-// iff the base is)", according to Itanium C++ ABI, 2.95p6b.
-static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
- // Check the number of bases.
- if (RD->getNumBases() != 1)
- return false;
-
- // Get the base.
- CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin();
-
- // Check that the base is not virtual.
- if (Base->isVirtual())
- return false;
-
- // Check that the base is public.
- if (Base->getAccessSpecifier() != AS_public)
- return false;
-
- // Check that the class is dynamic iff the base is.
- auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();
- if (!BaseDecl->isEmpty() &&
- BaseDecl->isDynamicClass() != RD->isDynamicClass())
- return false;
-
- return true;
-}
-
void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty,
llvm::Constant *StorageAddress) {
- // abi::__class_type_info.
- static const char * const ClassTypeInfo =
- "_ZTVN10__cxxabiv117__class_type_infoE";
- // abi::__si_class_type_info.
- static const char * const SIClassTypeInfo =
- "_ZTVN10__cxxabiv120__si_class_type_infoE";
- // abi::__vmi_class_type_info.
- static const char * const VMIClassTypeInfo =
- "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
-
- const char *VTableName = nullptr;
-
- switch (Ty->getTypeClass()) {
-#define TYPE(Class, Base)
-#define ABSTRACT_TYPE(Class, Base)
-#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
-#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
-#define DEPENDENT_TYPE(Class, Base) case Type::Class:
-#include "clang/AST/TypeNodes.inc"
- llvm_unreachable("Non-canonical and dependent types shouldn't get here");
-
- case Type::LValueReference:
- case Type::RValueReference:
- llvm_unreachable("References shouldn't get here");
-
- case Type::Auto:
- case Type::DeducedTemplateSpecialization:
- llvm_unreachable("Undeduced type shouldn't get here");
-
- case Type::Pipe:
- llvm_unreachable("Pipe types shouldn't get here");
-
- case Type::ArrayParameter:
- llvm_unreachable("Array Parameter types should not get here.");
-
- case Type::Builtin:
- case Type::BitInt:
- // GCC treats vector and complex types as fundamental types.
- case Type::Vector:
- case Type::ExtVector:
- case Type::ConstantMatrix:
- case Type::Complex:
- case Type::Atomic:
- // FIXME: GCC treats block pointers as fundamental types?!
- case Type::BlockPointer:
- // abi::__fundamental_type_info.
- VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE";
- break;
-
- case Type::ConstantArray:
- case Type::IncompleteArray:
- case Type::VariableArray:
- // abi::__array_type_info.
- VTableName = "_ZTVN10__cxxabiv117__array_type_infoE";
- break;
-
- case Type::FunctionNoProto:
- case Type::FunctionProto:
- // abi::__function_type_info.
- VTableName = "_ZTVN10__cxxabiv120__function_type_infoE";
- break;
-
- case Type::Enum:
- // abi::__enum_type_info.
- VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE";
- break;
-
- case Type::Record: {
- const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(cast<RecordType>(Ty)->getOriginalDecl())
- ->getDefinitionOrSelf();
-
- if (!RD->hasDefinition() || !RD->getNumBases()) {
- VTableName = ClassTypeInfo;
- } else if (CanUseSingleInheritance(RD)) {
- VTableName = SIClassTypeInfo;
- } else {
- VTableName = VMIClassTypeInfo;
- }
-
- break;
- }
-
- case Type::ObjCObject:
- // Ignore protocol qualifiers.
- Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr();
-
- // Handle id and Class.
- if (isa<BuiltinType>(Ty)) {
- VTableName = ClassTypeInfo;
- break;
- }
-
- assert(isa<ObjCInterfaceType>(Ty));
- [[fallthrough]];
-
- case Type::ObjCInterface:
- if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {
- VTableName = SIClassTypeInfo;
- } else {
- VTableName = ClassTypeInfo;
- }
- break;
-
- case Type::ObjCObjectPointer:
- case Type::Pointer:
- // abi::__pointer_type_info.
- VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE";
- break;
-
- case Type::MemberPointer:
- // abi::__pointer_to_member_type_info.
- VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
- break;
-
- case Type::HLSLAttributedResource:
- case Type::HLSLInlineSpirv:
- llvm_unreachable("HLSL doesn't support virtual functions");
- }
-
+ const char *VTableName = VTableClassNameForType(Ty);
llvm::Constant *VTable = nullptr;
// Check if the alias exists. If it doesn't, then get or create the global.
@@ -4168,7 +3792,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) {
llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
llvm::GlobalValue::DefaultStorageClass;
- if (auto RD = Ty->getAsCXXRecordDecl()) {
+ if (auto *RD = Ty->getAsCXXRecordDecl()) {
if ((CGM.getTriple().isWindowsItaniumEnvironment() &&
RD->hasAttr<DLLExportAttr>()) ||
(CGM.shouldMapVisibilityToDLLExport(RD) &&
@@ -4410,64 +4034,6 @@ void ItaniumRTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
Fields.push_back(BaseTypeInfo);
}
-namespace {
- /// SeenBases - Contains virtual and non-virtual bases seen when traversing
- /// a class hierarchy.
- struct SeenBases {
- llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
- llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
- };
-}
-
-/// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in
-/// abi::__vmi_class_type_info.
-///
-static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
- SeenBases &Bases) {
-
- unsigned Flags = 0;
-
- auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();
- if (Base->isVirtual()) {
- // Mark the virtual base as seen.
- if (!Bases.VirtualBases.insert(BaseDecl).second) {
- // If this virtual base has been seen before, then the class is diamond
- // shaped.
- Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;
- } else {
- if (Bases.NonVirtualBases.count(BaseDecl))
- Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
- }
- } else {
- // Mark the non-virtual base as seen.
- if (!Bases.NonVirtualBases.insert(BaseDecl).second) {
- // If this non-virtual base has been seen before, then the class has non-
- // diamond shaped repeated inheritance.
- Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
- } else {
- if (Bases.VirtualBases.count(BaseDecl))
- Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
- }
- }
-
- // Walk all bases.
- for (const auto &I : BaseDecl->bases())
- Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases);
-
- return Flags;
-}
-
-static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {
- unsigned Flags = 0;
- SeenBases Bases;
-
- // Walk all bases.
- for (const auto &I : RD->bases())
- Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases);
-
- return Flags;
-}
-
/// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
/// classes with bases that do not satisfy the abi::__si_class_type_info
/// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
@@ -4554,35 +4120,6 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
}
}
-/// Compute the flags for a __pbase_type_info, and remove the corresponding
-/// pieces from \p Type.
-static unsigned extractPBaseFlags(ASTContext &Ctx, QualType &Type) {
- unsigned Flags = 0;
-
- if (Type.isConstQualified())
- Flags |= ItaniumRTTIBuilder::PTI_Const;
- if (Type.isVolatileQualified())
- Flags |= ItaniumRTTIBuilder::PTI_Volatile;
- if (Type.isRestrictQualified())
- Flags |= ItaniumRTTIBuilder::PTI_Restrict;
- Type = Type.getUnqualifiedType();
-
- // Itanium C++ ABI 2.9.5p7:
- // When the abi::__pbase_type_info is for a direct or indirect pointer to an
- // incomplete class type, the incomplete target type flag is set.
- if (ContainsIncompleteClassType(Type))
- Flags |= ItaniumRTTIBuilder::PTI_Incomplete;
-
- if (auto *Proto = Type->getAs<FunctionProtoType>()) {
- if (Proto->isNothrow()) {
- Flags |= ItaniumRTTIBuilder::PTI_Noexcept;
- Type = Ctx.getFunctionTypeWithExceptionSpec(Type, EST_None);
- }
- }
-
- return Flags;
-}
-
/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
/// used for pointer types.
void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
diff --git a/clang/lib/CodeGenShared/CMakeLists.txt b/clang/lib/CodeGenShared/CMakeLists.txt
new file mode 100644
index 0000000000000..0e2cb50dccd2a
--- /dev/null
+++ b/clang/lib/CodeGenShared/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+add_clang_library(clangCodeGenShared
+ ItaniumRTTIBuilder.cpp
+
+ DEPENDS
+ LINK_LIBS
+ clangAST
+ )
diff --git a/clang/lib/CodeGenShared/ItaniumRTTIBuilder.cpp b/clang/lib/CodeGenShared/ItaniumRTTIBuilder.cpp
new file mode 100644
index 0000000000000..1932d1e282d57
--- /dev/null
+++ b/clang/lib/CodeGenShared/ItaniumRTTIBuilder.cpp
@@ -0,0 +1,418 @@
+//===--- ItaniumRTTIBuilder.cpp - LLVM Backend Utilities --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGenShared/ItaniumRTTIBuilder.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+
+namespace clang::CodeGenShared {
+
+/// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type
+/// info for that type is defined in the standard library.
+bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
+ // Itanium C++ ABI 2.9.2:
+ // Basic type information (e.g. for "int", "bool", etc.) will be kept in
+ // the run-time support library. Specifically, the run-time support
+ // library should contain type_info objects for the types X, X* and
+ // X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char,
+ // unsigned char, signed char, short, unsigned short, int, unsigned int,
+ // long, unsigned long, long long, unsigned long long, float, double,
+ // long double, char16_t, char32_t, and the IEEE 754r decimal and
+ // half-precision floating point types.
+ //
+ // GCC also emits RTTI for __int128.
+ // FIXME: We do not emit RTTI information for decimal types here.
+
+ // Types added here must also be added to EmitFundamentalRTTIDescriptors.
+ switch (Ty->getKind()) {
+ case BuiltinType::Void:
+ case BuiltinType::NullPtr:
+ case BuiltinType::Bool:
+ case BuiltinType::WChar_S:
+ case BuiltinType::WChar_U:
+ case BuiltinType::Char_U:
+ case BuiltinType::Char_S:
+ case BuiltinType::UChar:
+ case BuiltinType::SChar:
+ case BuiltinType::Short:
+ case BuiltinType::UShort:
+ case BuiltinType::Int:
+ case BuiltinType::UInt:
+ case BuiltinType::Long:
+ case BuiltinType::ULong:
+ case BuiltinType::LongLong:
+ case BuiltinType::ULongLong:
+ case BuiltinType::Half:
+ case BuiltinType::Float:
+ case BuiltinType::Double:
+ case BuiltinType::LongDouble:
+ case BuiltinType::Float16:
+ case BuiltinType::Float128:
+ case BuiltinType::Ibm128:
+ case BuiltinType::Char8:
+ case BuiltinType::Char16:
+ case BuiltinType::Char32:
+ case BuiltinType::Int128:
+ case BuiltinType::UInt128:
+ return true;
+
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLImageTypes.def"
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) case BuiltinType::Id:
+#include "clang/Basic/OpenCLExtensionTypes.def"
+ case BuiltinType::OCLSampler:
+ case BuiltinType::OCLEvent:
+ case BuiltinType::OCLClkEvent:
+ case BuiltinType::OCLQueue:
+ case BuiltinType::OCLReserveID:
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/AArch64ACLETypes.def"
+#define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:
+#include "clang/Basic/PPCTypes.def"
+#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/RISCVVTypes.def"
+#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/WebAssemblyReferenceTypes.def"
+#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
+#include "clang/Basic/AMDGPUTypes.def"
+#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+#include "clang/Basic/HLSLIntangibleTypes.def"
+ case BuiltinType::ShortAccum:
+ case BuiltinType::Accum:
+ case BuiltinType::LongAccum:
+ case BuiltinType::UShortAccum:
+ case BuiltinType::UAccum:
+ case BuiltinType::ULongAccum:
+ case BuiltinType::ShortFract:
+ case BuiltinType::Fract:
+ case BuiltinType::LongFract:
+ case BuiltinType::UShortFract:
+ case BuiltinType::UFract:
+ case BuiltinType::ULongFract:
+ case BuiltinType::SatShortAccum:
+ case BuiltinType::SatAccum:
+ case BuiltinType::SatLongAccum:
+ case BuiltinType::SatUShortAccum:
+ case BuiltinType::SatUAccum:
+ case BuiltinType::SatULongAccum:
+ case BuiltinType::SatShortFract:
+ case BuiltinType::SatFract:
+ case BuiltinType::SatLongFract:
+ case BuiltinType::SatUShortFract:
+ case BuiltinType::SatUFract:
+ case BuiltinType::SatULongFract:
+ case BuiltinType::BFloat16:
+ return false;
+
+ case BuiltinType::Dependent:
+#define BUILTIN_TYPE(Id, SingletonId)
+#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
+#include "clang/AST/BuiltinTypes.def"
+ llvm_unreachable("asking for RRTI for a placeholder type!");
+
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ llvm_unreachable("FIXME: Objective-C types are unsupported!");
+ }
+
+ llvm_unreachable("Invalid BuiltinType Kind!");
+}
+
+bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) {
+ QualType PointeeTy = PointerTy->getPointeeType();
+ const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(PointeeTy);
+ if (!BuiltinTy)
+ return false;
+
+ // Check the qualifiers.
+ Qualifiers Quals = PointeeTy.getQualifiers();
+ Quals.removeConst();
+
+ if (!Quals.empty())
+ return false;
+
+ return TypeInfoIsInStandardLibrary(BuiltinTy);
+}
+
+/// IsStandardLibraryRTTIDescriptor - Returns whether the type
+/// information for the given type exists in the standard library.
+bool IsStandardLibraryRTTIDescriptor(QualType Ty) {
+ // Type info for builtin types is defined in the standard library.
+ if (const BuiltinType *BuiltinTy = dyn_cast<BuiltinType>(Ty))
+ return TypeInfoIsInStandardLibrary(BuiltinTy);
+
+ // Type info for some pointer types to builtin types is defined in the
+ // standard library.
+ if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
+ return TypeInfoIsInStandardLibrary(PointerTy);
+
+ return false;
+}
+
+/// IsIncompleteClassType - Returns whether the given record type is incomplete.
+bool IsIncompleteClassType(const RecordType *RecordTy) {
+ return !RecordTy->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->isCompleteDefinition();
+}
+
+/// ContainsIncompleteClassType - Returns whether the given type contains an
+/// incomplete class type. This is true if
+///
+/// * The given type is an incomplete class type.
+/// * The given type is a pointer type whose pointee type contains an
+/// incomplete class type.
+/// * The given type is a member pointer type whose class is an incomplete
+/// class type.
+/// * The given type is a member pointer type whoise pointee type contains an
+/// incomplete class type.
+/// is an indirect or direct pointer to an incomplete class type.
+bool ContainsIncompleteClassType(QualType Ty) {
+ if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
+ if (IsIncompleteClassType(RecordTy))
+ return true;
+ }
+
+ if (const PointerType *PointerTy = dyn_cast<PointerType>(Ty))
+ return ContainsIncompleteClassType(PointerTy->getPointeeType());
+
+ if (const MemberPointerType *MemberPointerTy =
+ dyn_cast<MemberPointerType>(Ty)) {
+ // Check if the class type is incomplete.
+ if (!MemberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())
+ return true;
+
+ return ContainsIncompleteClassType(MemberPointerTy->getPointeeType());
+ }
+
+ return false;
+}
+
+// CanUseSingleInheritance - Return whether the given record decl has a "single,
+// public, non-virtual base at offset zero (i.e. the derived class is dynamic
+// iff the base is)", according to Itanium C++ ABI, 2.95p6b.
+bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
+ // Check the number of bases.
+ if (RD->getNumBases() != 1)
+ return false;
+
+ // Get the base.
+ CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin();
+
+ // Check that the base is not virtual.
+ if (Base->isVirtual())
+ return false;
+
+ // Check that the base is public.
+ if (Base->getAccessSpecifier() != AS_public)
+ return false;
+
+ // Check that the class is dynamic iff the base is.
+ auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();
+ if (!BaseDecl->isEmpty() &&
+ BaseDecl->isDynamicClass() != RD->isDynamicClass())
+ return false;
+
+ return true;
+}
+
+const char *VTableClassNameForType(const Type *Ty) {
+ // abi::__class_type_info.
+ static const char *const ClassTypeInfo =
+ "_ZTVN10__cxxabiv117__class_type_infoE";
+ // abi::__si_class_type_info.
+ static const char *const SIClassTypeInfo =
+ "_ZTVN10__cxxabiv120__si_class_type_infoE";
+ // abi::__vmi_class_type_info.
+ static const char *const VMIClassTypeInfo =
+ "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
+
+ switch (Ty->getTypeClass()) {
+#define TYPE(Class, Base)
+#define ABSTRACT_TYPE(Class, Base)
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
+#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
+#define DEPENDENT_TYPE(Class, Base) case Type::Class:
+#include "clang/AST/TypeNodes.inc"
+ llvm_unreachable("Non-canonical and dependent types shouldn't get here");
+
+ case Type::LValueReference:
+ case Type::RValueReference:
+ llvm_unreachable("References shouldn't get here");
+
+ case Type::Auto:
+ case Type::DeducedTemplateSpecialization:
+ llvm_unreachable("Undeduced type shouldn't get here");
+
+ case Type::Pipe:
+ llvm_unreachable("Pipe types shouldn't get here");
+
+ case Type::ArrayParameter:
+ llvm_unreachable("Array Parameter types should not get here.");
+
+ case Type::Builtin:
+ case Type::BitInt:
+ // GCC treats vector and complex types as fundamental types.
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::ConstantMatrix:
+ case Type::Complex:
+ case Type::Atomic:
+ // FIXME: GCC treats block pointers as fundamental types?!
+ case Type::BlockPointer:
+ // abi::__fundamental_type_info.
+ return "_ZTVN10__cxxabiv123__fundamental_type_infoE";
+
+ case Type::ConstantArray:
+ case Type::IncompleteArray:
+ case Type::VariableArray:
+ // abi::__array_type_info.
+ return "_ZTVN10__cxxabiv117__array_type_infoE";
+
+ case Type::FunctionNoProto:
+ case Type::FunctionProto:
+ // abi::__function_type_info.
+ return "_ZTVN10__cxxabiv120__function_type_infoE";
+
+ case Type::Enum:
+ // abi::__enum_type_info.
+ return "_ZTVN10__cxxabiv116__enum_type_infoE";
+
+ case Type::Record: {
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(cast<RecordType>(Ty)->getOriginalDecl())
+ ->getDefinitionOrSelf();
+
+ if (!RD->hasDefinition() || !RD->getNumBases()) {
+ return ClassTypeInfo;
+ }
+
+ if (CanUseSingleInheritance(RD)) {
+ return SIClassTypeInfo;
+ }
+
+ return VMIClassTypeInfo;
+ }
+
+ case Type::ObjCObject:
+ // Ignore protocol qualifiers.
+ Ty = cast<ObjCObjectType>(Ty)->getBaseType().getTypePtr();
+
+ // Handle id and Class.
+ if (isa<BuiltinType>(Ty)) {
+ return ClassTypeInfo;
+ }
+
+ assert(isa<ObjCInterfaceType>(Ty));
+ [[fallthrough]];
+
+ case Type::ObjCInterface:
+ if (cast<ObjCInterfaceType>(Ty)->getDecl()->getSuperClass()) {
+ return SIClassTypeInfo;
+ } else {
+ return ClassTypeInfo;
+ }
+
+ case Type::ObjCObjectPointer:
+ case Type::Pointer:
+ // abi::__pointer_type_info.
+ return "_ZTVN10__cxxabiv119__pointer_type_infoE";
+
+ case Type::MemberPointer:
+ // abi::__pointer_to_member_type_info.
+ return "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
+
+ case Type::HLSLAttributedResource:
+ case Type::HLSLInlineSpirv:
+ llvm_unreachable("HLSL doesn't support virtual functions");
+ }
+
+ return nullptr;
+}
+
+/// Compute the flags for a __pbase_type_info, and remove the corresponding
+/// pieces from \p Type.
+unsigned extractPBaseFlags(ASTContext &Ctx, QualType &Type) {
+ unsigned Flags = 0;
+
+ if (Type.isConstQualified())
+ Flags |= PTI_Const;
+ if (Type.isVolatileQualified())
+ Flags |= PTI_Volatile;
+ if (Type.isRestrictQualified())
+ Flags |= PTI_Restrict;
+ Type = Type.getUnqualifiedType();
+
+ // Itanium C++ ABI 2.9.5p7:
+ // When the abi::__pbase_type_info is for a direct or indirect pointer to an
+ // incomplete class type, the incomplete target type flag is set.
+ if (ContainsIncompleteClassType(Type))
+ Flags |= PTI_Incomplete;
+
+ if (auto *Proto = Type->getAs<FunctionProtoType>()) {
+ if (Proto->isNothrow()) {
+ Flags |= PTI_Noexcept;
+ Type = Ctx.getFunctionTypeWithExceptionSpec(Type, EST_None);
+ }
+ }
+
+ return Flags;
+}
+
+/// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in
+/// abi::__vmi_class_type_info.
+///
+unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
+ SeenBases &Bases) {
+
+ unsigned Flags = 0;
+
+ auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();
+ if (Base->isVirtual()) {
+ // Mark the virtual base as seen.
+ if (!Bases.VirtualBases.insert(BaseDecl).second) {
+ // If this virtual base has been seen before, then the class is diamond
+ // shaped.
+ Flags |= VMI_DiamondShaped;
+ } else {
+ if (Bases.NonVirtualBases.count(BaseDecl))
+ Flags |= VMI_NonDiamondRepeat;
+ }
+ } else {
+ // Mark the non-virtual base as seen.
+ if (!Bases.NonVirtualBases.insert(BaseDecl).second) {
+ // If this non-virtual base has been seen before, then the class has non-
+ // diamond shaped repeated inheritance.
+ Flags |= VMI_NonDiamondRepeat;
+ } else {
+ if (Bases.VirtualBases.count(BaseDecl))
+ Flags |= VMI_NonDiamondRepeat;
+ }
+ }
+
+ // Walk all bases.
+ for (const auto &I : BaseDecl->bases())
+ Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases);
+
+ return Flags;
+}
+
+unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {
+ unsigned Flags = 0;
+ SeenBases Bases;
+
+ // Walk all bases.
+ for (const auto &I : RD->bases())
+ Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases);
+
+ return Flags;
+}
+} // namespace clang::CodeGenShared
More information about the cfe-commits
mailing list