https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/223423
>From 44c041086f7cd58fd5bf30b322ea41175143f307 Mon Sep 17 00:00:00 2001 From: Henrich Lauko <[email protected]> Date: Tue, 29 Sep 2026 09:55:27 +0000 Subject: [PATCH 1/3] [CIR][CodeGen][NFC] Share the Itanium __vmi_class_type_info flags computation Both CodeGens carry the same abi::__vmi_class_type_info and abi::__base_class_type_info flag values and the same recursive walk over the bases that computes the __flags word. They join the __pbase_type_info flags in ItaniumCXXABIUtils.h, named VMIClassTypeInfoFlags and BaseClassTypeInfoFlags. CIR's copy was equivalent modulo naming and was marked "TODO(cir): Will be removed after sharing them with the classical codegen". No functional change intended. --- .../clang/CodeGenUtils/ItaniumCXXABIUtils.h | 21 +++++ clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 80 +----------------- clang/lib/CodeGen/ItaniumCXXABI.cpp | 82 +------------------ clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp | 54 ++++++++++++ 4 files changed, 81 insertions(+), 156 deletions(-) diff --git a/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h b/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h index fb125e796aa19..59b94c9bb08c3 100644 --- a/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h +++ b/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h @@ -44,10 +44,31 @@ enum PointerTypeInfoFlags { PTI_Noexcept = 0x40, }; +/// Flags for abi::__vmi_class_type_info. +enum VMIClassTypeInfoFlags { + /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance. + VMI_NonDiamondRepeat = 0x1, + + /// VMI_DiamondShaped - Class is diamond shaped. + VMI_DiamondShaped = 0x2 +}; + +/// Flags for abi::__base_class_type_info. +enum BaseClassTypeInfoFlags { + /// BCTI_Virtual - Base class is virtual. + BCTI_Virtual = 0x1, + + /// BCTI_Public - Base class is public. + BCTI_Public = 0x2 +}; + /// Compute the src2dst_offset hint as described in the Itanium C++ ABI [2.9.7]. CharUnits computeOffsetHint(ASTContext &Ctx, const CXXRecordDecl *Src, const CXXRecordDecl *Dst); +/// Compute the value of the flags member in abi::__vmi_class_type_info. +unsigned computeVMIClassTypeInfoFlags(const CXXRecordDecl *RD); + /// Returns whether the given type contains an incomplete class type. This is /// true if /// diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index a4acd242eee1a..397d8f43895e6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -638,27 +638,8 @@ class CIRGenItaniumRTTIBuilder { }; } // namespace -// TODO(cir): Will be removed after sharing them with the classical codegen namespace { -// 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 -}; - /// Given a builtin type, returns whether the type /// info for that type is defined in the standard library. /// TODO(cir): this can unified with LLVM codegen @@ -850,61 +831,6 @@ static bool shouldUseExternalRttiDescriptor(CIRGenModule &cgm, QualType ty) { return false; } -/// 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; -}; - -/// 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 |= 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 &bs : baseDecl->bases()) - flags |= computeVmiClassTypeInfoFlags(&bs, bases); - - return flags; -} - -static unsigned computeVmiClassTypeInfoFlags(const CXXRecordDecl *rd) { - unsigned flags = 0; - SeenBases bases; - - // Walk all bases. - for (const auto &bs : rd->bases()) - flags |= computeVmiClassTypeInfoFlags(&bs, bases); - - return flags; -} - // 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. @@ -1213,7 +1139,7 @@ void CIRGenItaniumRTTIBuilder::buildVMIClassTypeInfo(mlir::Location loc, // __flags is a word with flags describing details about the class // structure, which may be referenced by using the __flags_masks // enumeration. These flags refer to both direct and indirect bases. - unsigned flags = computeVmiClassTypeInfoFlags(rd); + unsigned flags = CodeGenUtils::computeVMIClassTypeInfoFlags(rd); fields.push_back(cir::IntAttr::get(unsignedIntLTy, flags)); // Itanium C++ ABI 2.9.5p6c: @@ -1280,9 +1206,9 @@ void CIRGenItaniumRTTIBuilder::buildVMIClassTypeInfo(mlir::Location loc, // The low-order byte of __offset_flags contains flags, as given by the // masks from the enumeration __offset_flags_masks. if (base.isVirtual()) - offsetFlags |= BCTI_Virtual; + offsetFlags |= CodeGenUtils::BCTI_Virtual; if (base.getAccessSpecifier() == AS_public) - offsetFlags |= BCTI_Public; + offsetFlags |= CodeGenUtils::BCTI_Public; fields.push_back(cir::IntAttr::get(offsetFlagsLTy, offsetFlags)); } diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index f97871a3a2523..228a2a6e689da 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3545,24 +3545,6 @@ class ItaniumRTTIBuilder { ItaniumRTTIBuilder(const ItaniumCXXABI &ABI) : CGM(ABI.CGM), VMContext(CGM.getModule().getContext()), CXXABI(ABI) {} - // 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); @@ -4378,64 +4360,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. @@ -4447,7 +4371,7 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) { // __flags is a word with flags describing details about the class // structure, which may be referenced by using the __flags_masks // enumeration. These flags refer to both direct and indirect bases. - unsigned Flags = ComputeVMIClassTypeInfoFlags(RD); + unsigned Flags = CodeGenUtils::computeVMIClassTypeInfoFlags(RD); Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); // Itanium C++ ABI 2.9.5p6c: @@ -4514,9 +4438,9 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) { // The low-order byte of __offset_flags contains flags, as given by the // masks from the enumeration __offset_flags_masks. if (Base.isVirtual()) - OffsetFlags |= BCTI_Virtual; + OffsetFlags |= CodeGenUtils::BCTI_Virtual; if (Base.getAccessSpecifier() == AS_public) - OffsetFlags |= BCTI_Public; + OffsetFlags |= CodeGenUtils::BCTI_Public; Fields.push_back(llvm::ConstantInt::getSigned(OffsetFlagsLTy, OffsetFlags)); } diff --git a/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp b/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp index 1073be5a76acf..a1ab26cfc17b0 100644 --- a/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp +++ b/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp @@ -61,6 +61,60 @@ CharUnits computeOffsetHint(ASTContext &Ctx, const CXXRecordDecl *Src, return Offset; } +namespace { +/// 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; +}; +} // namespace + +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 |= 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; +} + /// Returns whether the given record type is incomplete. static bool isIncompleteClassType(const RecordType *RecordTy) { return !RecordTy->getDecl()->getDefinitionOrSelf()->isCompleteDefinition(); >From 725ee5437a7564dc3a691b74e1ed7304b4116725 Mon Sep 17 00:00:00 2001 From: Henrich Lauko <[email protected]> Date: Tue, 29 Sep 2026 09:55:33 +0000 Subject: [PATCH 2/3] [CIR][CodeGen][NFC] Share canUseSingleInheritance Both CodeGens carry the same predicate deciding whether a class gets an abi::__si_class_type_info. CIR's copy was marked "TODO(cir): this can unified with LLVM codegen" and differed from classic only in spelling the final check as one boolean expression; the shared version keeps that form. No functional change intended. --- .../clang/CodeGenUtils/ItaniumCXXABIUtils.h | 5 +++ clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 30 ++--------------- clang/lib/CodeGen/ItaniumCXXABI.cpp | 32 ++----------------- clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp | 22 +++++++++++++ 4 files changed, 31 insertions(+), 58 deletions(-) diff --git a/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h b/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h index 59b94c9bb08c3..9d6a20ef82ab3 100644 --- a/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h +++ b/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h @@ -62,6 +62,11 @@ enum BaseClassTypeInfoFlags { BCTI_Public = 0x2 }; +/// 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); + /// Compute the src2dst_offset hint as described in the Itanium C++ ABI [2.9.7]. CharUnits computeOffsetHint(ASTContext &Ctx, const CXXRecordDecl *Src, const CXXRecordDecl *Dst); diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index 397d8f43895e6..cdc94838f5674 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -831,32 +831,6 @@ static bool shouldUseExternalRttiDescriptor(CIRGenModule &cgm, QualType ty) { return false; } -// 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. -// TODO(cir): this can unified with LLVM codegen -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(); - return baseDecl->isEmpty() || - baseDecl->isDynamicClass() == rd->isDynamicClass(); -} - const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) { // abi::__class_type_info. static const char *const classTypeInfo = @@ -925,7 +899,7 @@ const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) { return classTypeInfo; } - if (canUseSingleInheritance(rd)) { + if (CodeGenUtils::canUseSingleInheritance(rd)) { return siClassTypeInfo; } @@ -1421,7 +1395,7 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo( break; } - if (canUseSingleInheritance(rd)) { + if (CodeGenUtils::canUseSingleInheritance(rd)) { buildSIClassTypeInfo(loc, rd); } else { buildVMIClassTypeInfo(loc, rd); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 228a2a6e689da..f7dedeaeb31bf 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3819,34 +3819,6 @@ static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, 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. @@ -3923,7 +3895,7 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty, if (!RD->hasDefinition() || !RD->getNumBases()) { VTableName = ClassTypeInfo; - } else if (CanUseSingleInheritance(RD)) { + } else if (CodeGenUtils::canUseSingleInheritance(RD)) { VTableName = SIClassTypeInfo; } else { VTableName = VMIClassTypeInfo; @@ -4241,7 +4213,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( break; } - if (CanUseSingleInheritance(RD)) + if (CodeGenUtils::canUseSingleInheritance(RD)) BuildSIClassTypeInfo(RD); else BuildVMIClassTypeInfo(RD); diff --git a/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp b/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp index a1ab26cfc17b0..2f22ab69d4c5a 100644 --- a/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp +++ b/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp @@ -61,6 +61,28 @@ CharUnits computeOffsetHint(ASTContext &Ctx, const CXXRecordDecl *Src, return Offset; } +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(); + return BaseDecl->isEmpty() || + BaseDecl->isDynamicClass() == RD->isDynamicClass(); +} + namespace { /// Contains virtual and non-virtual bases seen when traversing a class /// hierarchy. >From 83f2a8ae669dd6ef86390b39915932076967d4e7 Mon Sep 17 00:00:00 2001 From: Henrich Lauko <[email protected]> Date: Mon, 14 Sep 2026 13:35:53 +0000 Subject: [PATCH 3/3] [CIR][CodeGen] Share isStandardLibraryRTTIDescriptor Takes the classic implementation as the shared one. CIR's copy was already marked "TODO(cir): this can unified with LLVM codegen". CIR's builtin-type switch was missing the WASM_TYPE and HLSL_INTANGIBLE_TYPE .def expansions and hit llvm_unreachable("NYI") on WasmExternRef and HLSLResource instead. Classic CodeGen groups both with the types whose type_info is not in the standard library, so CIR no longer aborts on them. Neither case is reachable today: CIR rejects the Wasm C++ ABI before RTTI emission, and HLSL has no typeid. No change in test output. --- .../clang/CodeGenUtils/ItaniumCXXABIUtils.h | 4 + clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 151 +---------------- clang/lib/CodeGen/ItaniumCXXABI.cpp | 155 +----------------- clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp | 145 ++++++++++++++++ 4 files changed, 153 insertions(+), 302 deletions(-) diff --git a/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h b/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h index 9d6a20ef82ab3..70f32df5f8e99 100644 --- a/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h +++ b/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h @@ -90,6 +90,10 @@ bool containsIncompleteClassType(QualType Ty); /// pieces from \p Type. unsigned extractPBaseFlags(const ASTContext &Ctx, QualType &Type); +/// Returns whether the type information for the given type exists in the +/// standard library. +bool isStandardLibraryRTTIDescriptor(QualType Ty); + } // namespace clang::CodeGenUtils #endif // LLVM_CLANG_CODEGENUTILS_ITANIUMCXXABIUTILS_H diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp index cdc94838f5674..aa7e95ef398ad 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -636,155 +636,6 @@ class CIRGenItaniumRTTIBuilder { cir::GlobalLinkageKind linkage, mlir::SymbolTable::Visibility visibility); }; -} // namespace - -namespace { - -/// Given a builtin type, returns whether the type -/// info for that type is defined in the standard library. -/// TODO(cir): this can unified with LLVM codegen -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::WasmExternRef: - case BuiltinType::HLSLResource: - llvm_unreachable("NYI"); - 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 AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id: -#include "clang/Basic/AMDGPUTypes.def" -#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: -#include "clang/Basic/SPIRVTypes.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 auto *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 auto *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 auto *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 @@ -1274,7 +1125,7 @@ mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(mlir::Location loc, } // Check if there is already an external RTTI descriptor for this type. - if (isStandardLibraryRttiDescriptor(ty) || + if (CodeGenUtils::isStandardLibraryRTTIDescriptor(ty) || shouldUseExternalRttiDescriptor(cgm, ty)) return getAddrOfExternalRTTIDescriptor(loc, ty); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index f7dedeaeb31bf..f1cd9ee27c7ed 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3623,156 +3623,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" -#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: -#include "clang/Basic/SPIRVTypes.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 @@ -4062,7 +3912,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) { } // Check if there is already an external RTTI descriptor for this type. - if (IsStandardLibraryRTTIDescriptor(Ty) || + if (CodeGenUtils::isStandardLibraryRTTIDescriptor(Ty) || ShouldUseExternalRTTIDescriptor(CGM, Ty)) return GetAddrOfExternalRTTIDescriptor(Ty); @@ -4477,7 +4327,8 @@ llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) { } void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) { - // Types added here must also be added to TypeInfoIsInStandardLibrary. + // Types added here must also be added to typeInfoIsInStandardLibrary in + // clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp. QualType FundamentalTypes[] = { getContext().VoidTy, getContext().NullPtrTy, getContext().BoolTy, getContext().WCharTy, diff --git a/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp b/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp index 2f22ab69d4c5a..6265f21f2d0bd 100644 --- a/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp +++ b/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp @@ -189,4 +189,149 @@ unsigned extractPBaseFlags(const ASTContext &Ctx, QualType &Type) { return Flags; } +/// 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 in + // clang/lib/CodeGen/ItaniumCXXABI.cpp. + 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" +#define SPIRV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/SPIRVTypes.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); +} + +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; +} + } // namespace clang::CodeGenUtils _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
