https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/223422
>From 23f5e2f4e15d7c9d333991cf90aeef40cd896e9d Mon Sep 17 00:00:00 2001 From: Henrich Lauko <[email protected]> Date: Tue, 29 Sep 2026 09:55:22 +0000 Subject: [PATCH] [CIR][CodeGen][NFC] Share the Itanium __pbase_type_info flags and predicates Both CodeGens carry the same abi::__pbase_type_info flag values, the same containsIncompleteClassType predicate and the same extractPBaseFlags that computes the flags from a QualType. They come out of ItaniumCXXABI.cpp, so they join computeOffsetHint in ItaniumCXXABIUtils.h. The flag set gets a name, PointerTypeInfoFlags, now that it lives in a public header. CIR's copies were equivalent modulo naming. The __vmi_class_type_info and __base_class_type_info flags and canUseSingleInheritance stay behind for the next two patches. No functional change intended. --- .../clang/CodeGenUtils/ItaniumCXXABIUtils.h | 47 ++++++++- clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 96 ++---------------- clang/lib/CodeGen/ItaniumCXXABI.cpp | 99 +------------------ clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp | 52 ++++++++++ 4 files changed, 106 insertions(+), 188 deletions(-) diff --git a/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h b/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h index 45b358ad343bb..fb125e796aa19 100644 --- a/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h +++ b/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h @@ -6,9 +6,9 @@ // //===----------------------------------------------------------------------===// // -// This file holds the Itanium C++ ABI queries that both classic CodeGen and -// CIR CodeGen need while lowering ABI constructs whose encoding the ABI -// specifies in terms of the AST. +// This file holds the Itanium C++ ABI type_info flag values, together with +// the queries that both classic CodeGen and CIR CodeGen need while lowering +// ABI constructs whose encoding the ABI specifies in terms of the AST. // //===----------------------------------------------------------------------===// @@ -19,10 +19,51 @@ namespace clang::CodeGenUtils { +/// Flags for abi::__pbase_type_info. +enum PointerTypeInfoFlags { + /// 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, +}; + /// 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); +/// 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 whose pointee type contains an +/// incomplete class type. +bool containsIncompleteClassType(QualType Ty); + +/// Compute the flags for a __pbase_type_info, and remove the corresponding +/// pieces from \p Type. +unsigned extractPBaseFlags(const ASTContext &Ctx, QualType &Type); + } // 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 827f000ae573d..a4acd242eee1a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp @@ -641,31 +641,6 @@ class CIRGenItaniumRTTIBuilder { // TODO(cir): Will be removed after sharing them with the classical codegen namespace { -// 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. @@ -956,67 +931,6 @@ static bool canUseSingleInheritance(const CXXRecordDecl *rd) { baseDecl->isDynamicClass() == rd->isDynamicClass(); } -/// IsIncompleteClassType - Returns whether the given record type is incomplete. -static bool isIncompleteClassType(const RecordType *recordTy) { - return !recordTy->getDecl()->getDefinitionOrSelf()->isCompleteDefinition(); -} - -/// 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 auto *recordTy = dyn_cast<RecordType>(ty)) { - if (isIncompleteClassType(recordTy)) - return true; - } - - if (const auto *pointerTy = dyn_cast<PointerType>(ty)) - return containsIncompleteClassType(pointerTy->getPointeeType()); - - if (const auto *memberPointerTy = dyn_cast<MemberPointerType>(ty)) { - // Check if the class type is incomplete. - if (!memberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition()) - return true; - - return containsIncompleteClassType(memberPointerTy->getPointeeType()); - } - - return false; -} - -static unsigned extractPBaseFlags(const ASTContext &ctx, QualType &ty) { - unsigned flags = 0; - - if (ty.isConstQualified()) - flags |= PTI_Const; - if (ty.isVolatileQualified()) - flags |= PTI_Volatile; - if (ty.isRestrictQualified()) - flags |= PTI_Restrict; - - ty = ty.getUnqualifiedType(); - - if (containsIncompleteClassType(ty)) - flags |= PTI_Incomplete; - - if (const auto *proto = ty->getAs<FunctionProtoType>()) { - if (proto->isNothrow()) { - flags |= PTI_Noexcept; - ty = ctx.getFunctionTypeWithExceptionSpec(ty, EST_None); - } - } - - return flags; -} - const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) { // abi::__class_type_info. static const char *const classTypeInfo = @@ -1130,7 +1044,7 @@ static cir::GlobalLinkageKind getTypeInfoLinkage(CIRGenModule &cgm, // generated for the incomplete type that will not resolve to the final // complete class RTTI (because the latter need not exist), possibly by // making it a local static object. - if (containsIncompleteClassType(ty)) + if (CodeGenUtils::containsIncompleteClassType(ty)) return cir::GlobalLinkageKind::InternalLinkage; switch (ty->getLinkage()) { @@ -1395,7 +1309,8 @@ void CIRGenItaniumRTTIBuilder::buildPointerTypeInfo(mlir::Location loc, // __noexcept_mask = 0x40 // }; // }; - const unsigned int flags = extractPBaseFlags(cgm.getASTContext(), ty); + const unsigned int flags = + CodeGenUtils::extractPBaseFlags(cgm.getASTContext(), ty); mlir::Type unsignedIntTy = cgm.convertType(cgm.getASTContext().UnsignedIntTy); mlir::Attribute flagsAttr = cir::IntAttr::get(unsignedIntTy, flags); @@ -1418,11 +1333,12 @@ void CIRGenItaniumRTTIBuilder::buildPointerToMemberTypeInfo( // }; QualType pointeeTy = ty->getPointeeType(); - unsigned flags = extractPBaseFlags(cgm.getASTContext(), pointeeTy); + unsigned flags = + CodeGenUtils::extractPBaseFlags(cgm.getASTContext(), pointeeTy); const auto *rd = ty->getMostRecentCXXRecordDecl(); if (!rd->hasDefinition()) - flags |= PTI_ContainingClassIncomplete; + flags |= CodeGenUtils::PTI_ContainingClassIncomplete; mlir::Type unsignedIntTy = cgm.convertType(cgm.getASTContext().UnsignedIntTy); mlir::Attribute flagsAttr = cir::IntAttr::get(unsignedIntTy, flags); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 6dbf3fbbb0b12..f97871a3a2523 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3545,31 +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. @@ -3862,43 +3837,6 @@ static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, return false; } -/// IsIncompleteClassType - Returns whether the given record type is incomplete. -static bool IsIncompleteClassType(const RecordType *RecordTy) { - return !RecordTy->getDecl()->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. @@ -4100,7 +4038,7 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM, // generated for the incomplete type that will not resolve to the final // complete class RTTI (because the latter need not exist), possibly by // making it a local static object. - if (ContainsIncompleteClassType(Ty)) + if (CodeGenUtils::containsIncompleteClassType(Ty)) return llvm::GlobalValue::InternalLinkage; switch (Ty->getLinkage()) { @@ -4584,42 +4522,13 @@ 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) { // Itanium C++ ABI 2.9.5p7: // __flags is a flag word describing the cv-qualification and other // attributes of the type pointed to - unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy); + unsigned Flags = CodeGenUtils::extractPBaseFlags(CGM.getContext(), PointeeTy); llvm::Type *UnsignedIntLTy = CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); @@ -4642,11 +4551,11 @@ ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) { // Itanium C++ ABI 2.9.5p7: // __flags is a flag word describing the cv-qualification and other // attributes of the type pointed to. - unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy); + unsigned Flags = CodeGenUtils::extractPBaseFlags(CGM.getContext(), PointeeTy); const auto *RD = Ty->getMostRecentCXXRecordDecl(); if (!RD->hasDefinition()) - Flags |= PTI_ContainingClassIncomplete; + Flags |= CodeGenUtils::PTI_ContainingClassIncomplete; llvm::Type *UnsignedIntLTy = CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); diff --git a/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp b/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp index 9640bd23cca54..1073be5a76acf 100644 --- a/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp +++ b/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp @@ -61,4 +61,56 @@ CharUnits computeOffsetHint(ASTContext &Ctx, const CXXRecordDecl *Src, return Offset; } +/// Returns whether the given record type is incomplete. +static bool isIncompleteClassType(const RecordType *RecordTy) { + return !RecordTy->getDecl()->getDefinitionOrSelf()->isCompleteDefinition(); +} + +bool containsIncompleteClassType(QualType Ty) { + if (const auto *RecordTy = dyn_cast<RecordType>(Ty)) { + if (isIncompleteClassType(RecordTy)) + return true; + } + + if (const auto *PointerTy = dyn_cast<PointerType>(Ty)) + return containsIncompleteClassType(PointerTy->getPointeeType()); + + if (const auto *MemberPointerTy = dyn_cast<MemberPointerType>(Ty)) { + // Check if the class type is incomplete. + if (!MemberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition()) + return true; + + return containsIncompleteClassType(MemberPointerTy->getPointeeType()); + } + + return false; +} + +unsigned extractPBaseFlags(const 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; +} + } // namespace clang::CodeGenUtils _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
