[clang] [compiler-rt] [llvm] [WIP] Advance the merger progress of #211963 (PR #216611)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 16 16:45:49 PDT 2026
https://github.com/zhangweize9-cyber updated https://github.com/llvm/llvm-project/pull/216611
>From 3b6ef25ffb618a937b14a555d7585c45cb96779d Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Mon, 17 Aug 2026 07:08:38 +0800
Subject: [PATCH] [libc++][test] Mark `UNSUPPORTED` for a test relying on
`[[clang::trivial_abi]]` for compilers not supporting it (#211736)
This patch marks `UNSUPPORTED` for compilers not supporting
`[[clang::trivial_abi]]` (MSVC and GCC earlier than GCC 17) for a test
relying on this attribute.
---
clang/lib/CodeGen/ItaniumCXXABI.cpp | 744 +++++++++---------
.../invalid-pointer-pairs-vector-extract.cpp | 2 -
.../ExecutionEngine/Orc/SymbolLookupSet.h | 31 +-
llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 4 +-
.../AMDGPU/elementwise-fma-operand1.ll | 100 +--
.../ExecutionEngine/Orc/CMakeLists.txt | 1 -
.../Orc/SymbolLookupSetTest.cpp | 133 ----
.../unittests/ExecutionEngine/Orc/BUILD.gn | 1 -
orc-rt/include/CMakeLists.txt | 1 -
orc-rt/include/orc-rt/StringPool.h | 249 ------
orc-rt/test/unit/CMakeLists.txt | 1 -
orc-rt/test/unit/StringPoolTest.cpp | 166 ----
12 files changed, 380 insertions(+), 1053 deletions(-)
delete mode 100644 llvm/unittests/ExecutionEngine/Orc/SymbolLookupSetTest.cpp
delete mode 100644 orc-rt/include/orc-rt/StringPool.h
delete mode 100644 orc-rt/test/unit/StringPoolTest.cpp
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index c17813140b10f..9b3f0b84dea39 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -63,12 +63,10 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
}
public:
- ItaniumCXXABI(CodeGen::CodeGenModule &CGM,
- bool UseARMMethodPtrABI = false,
- bool UseARMGuardVarABI = false) :
- CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
- UseARMGuardVarABI(UseARMGuardVarABI),
- Use32BitVTableOffsetABI(false) { }
+ ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool UseARMMethodPtrABI = false,
+ bool UseARMGuardVarABI = false)
+ : CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
+ UseARMGuardVarABI(UseARMGuardVarABI), Use32BitVTableOffsetABI(false) {}
bool classifyReturnType(CGFunctionInfo &FI) const override;
@@ -130,12 +128,10 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override;
CGCallee
- EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
- const Expr *E,
- Address This,
- llvm::Value *&ThisPtrForCall,
- llvm::Value *MemFnPtr,
- const MemberPointerType *MPT) override;
+ EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E,
+ Address This, llvm::Value *&ThisPtrForCall,
+ llvm::Value *MemFnPtr,
+ const MemberPointerType *MPT) override;
llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
Address Base, llvm::Value *MemPtr,
@@ -157,14 +153,14 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
llvm::Constant *BuildMemberPointer(const CXXMethodDecl *MD,
CharUnits ThisAdjustment);
- llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
- llvm::Value *L, llvm::Value *R,
+ llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF, llvm::Value *L,
+ llvm::Value *R,
const MemberPointerType *MPT,
bool Inequality) override;
- llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
- llvm::Value *Addr,
- const MemberPointerType *MPT) override;
+ llvm::Value *
+ EmitMemberPointerIsNotNull(CodeGenFunction &CGF, llvm::Value *Addr,
+ const MemberPointerType *MPT) override;
void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE,
Address Ptr, QualType ElementType,
@@ -261,9 +257,9 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
bool EmitBadCastCall(CodeGenFunction &CGF) override;
llvm::Value *
- GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This,
- const CXXRecordDecl *ClassDecl,
- const CXXRecordDecl *BaseClassDecl) override;
+ GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This,
+ const CXXRecordDecl *ClassDecl,
+ const CXXRecordDecl *BaseClassDecl) override;
void EmitCXXConstructors(const CXXConstructorDecl *D) override;
@@ -369,17 +365,16 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
}
StringRef GetPureVirtualCallName() override { return "__cxa_pure_virtual"; }
- StringRef GetDeletedVirtualCallName() override
- { return "__cxa_deleted_virtual"; }
+ StringRef GetDeletedVirtualCallName() override {
+ return "__cxa_deleted_virtual";
+ }
CharUnits getArrayCookieSizeImpl(QualType elementType) override;
- Address InitializeArrayCookie(CodeGenFunction &CGF,
- Address NewPtr,
+ Address InitializeArrayCookie(CodeGenFunction &CGF, Address NewPtr,
llvm::Value *NumElements,
const CXXNewExpr *expr,
QualType ElementType) override;
- llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
- Address allocPtr,
+ llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, Address allocPtr,
CharUnits cookieSize) override;
void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
@@ -392,14 +387,12 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
llvm::Function *getOrCreateThreadLocalWrapper(const VarDecl *VD,
llvm::Value *Val);
void EmitThreadLocalInitFuncs(
- CodeGenModule &CGM,
- ArrayRef<const VarDecl *> CXXThreadLocals,
+ CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
ArrayRef<llvm::Function *> CXXThreadLocalInits,
ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override;
bool usesThreadWrapperFunction(const VarDecl *VD) const override {
- return !isEmittedWithConstantInitializer(VD) ||
- mayNeedDestruction(VD);
+ return !isEmittedWithConstantInitializer(VD) || mayNeedDestruction(VD);
}
LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
QualType LValType) override;
@@ -446,43 +439,43 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
LoadVTablePtr(CodeGenFunction &CGF, Address This,
const CXXRecordDecl *RD) override;
- private:
- llvm::Constant *
- getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD);
-
- bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {
- const auto &VtableLayout =
- CGM.getItaniumVTableContext().getVTableLayout(RD);
-
- for (const auto &VtableComponent : VtableLayout.vtable_components()) {
- // Skip empty slot.
- if (!VtableComponent.isUsedFunctionPointerKind())
- continue;
-
- const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
- const FunctionDecl *FD = Method->getDefinition();
- const bool IsInlined =
- Method->getCanonicalDecl()->isInlined() || (FD && FD->isInlined());
- if (!IsInlined)
- continue;
-
- StringRef Name = CGM.getMangledName(
- VtableComponent.getGlobalDecl(/*HasVectorDeletingDtors=*/false));
- auto *Entry = CGM.GetGlobalValue(Name);
- // This checks if virtual inline function has already been emitted.
- // Note that it is possible that this inline function would be emitted
- // after trying to emit vtable speculatively. Because of this we do
- // an extra pass after emitting all deferred vtables to find and emit
- // these vtables opportunistically.
- if (!Entry || Entry->isDeclaration())
- return true;
- }
- return false;
+private:
+ llvm::Constant *
+ getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD);
+
+ bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {
+ const auto &VtableLayout =
+ CGM.getItaniumVTableContext().getVTableLayout(RD);
+
+ for (const auto &VtableComponent : VtableLayout.vtable_components()) {
+ // Skip empty slot.
+ if (!VtableComponent.isUsedFunctionPointerKind())
+ continue;
+
+ const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
+ const FunctionDecl *FD = Method->getDefinition();
+ const bool IsInlined =
+ Method->getCanonicalDecl()->isInlined() || (FD && FD->isInlined());
+ if (!IsInlined)
+ continue;
+
+ StringRef Name = CGM.getMangledName(
+ VtableComponent.getGlobalDecl(/*HasVectorDeletingDtors=*/false));
+ auto *Entry = CGM.GetGlobalValue(Name);
+ // This checks if virtual inline function has already been emitted.
+ // Note that it is possible that this inline function would be emitted
+ // after trying to emit vtable speculatively. Because of this we do
+ // an extra pass after emitting all deferred vtables to find and emit
+ // these vtables opportunistically.
+ if (!Entry || Entry->isDeclaration())
+ return true;
+ }
+ return false;
}
bool isVTableHidden(const CXXRecordDecl *RD) const {
const auto &VtableLayout =
- CGM.getItaniumVTableContext().getVTableLayout(RD);
+ CGM.getItaniumVTableContext().getVTableLayout(RD);
for (const auto &VtableComponent : VtableLayout.vtable_components()) {
if (VtableComponent.isRTTIKind()) {
@@ -502,9 +495,9 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
class ARMCXXABI : public ItaniumCXXABI {
public:
- ARMCXXABI(CodeGen::CodeGenModule &CGM) :
- ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true,
- /*UseARMGuardVarABI=*/true) {}
+ ARMCXXABI(CodeGen::CodeGenModule &CGM)
+ : ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true,
+ /*UseARMGuardVarABI=*/true) {}
bool constructorsAndDestructorsReturnThis() const override { return true; }
@@ -512,8 +505,7 @@ class ARMCXXABI : public ItaniumCXXABI {
QualType ResTy) override;
CharUnits getArrayCookieSizeImpl(QualType elementType) override;
- Address InitializeArrayCookie(CodeGenFunction &CGF,
- Address NewPtr,
+ Address InitializeArrayCookie(CodeGenFunction &CGF, Address NewPtr,
llvm::Value *NumElements,
const CXXNewExpr *expr,
QualType ElementType) override;
@@ -533,8 +525,7 @@ class AppleARM64CXXABI : public ARMCXXABI {
class FuchsiaCXXABI final : public ItaniumCXXABI {
public:
- explicit FuchsiaCXXABI(CodeGen::CodeGenModule &CGM)
- : ItaniumCXXABI(CGM) {}
+ explicit FuchsiaCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM) {}
private:
bool constructorsAndDestructorsReturnThis() const override { return true; }
@@ -557,8 +548,7 @@ class WebAssemblyCXXABI final : public ItaniumCXXABI {
class XLCXXABI final : public ItaniumCXXABI {
public:
- explicit XLCXXABI(CodeGen::CodeGenModule &CGM)
- : ItaniumCXXABI(CGM) {}
+ explicit XLCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM) {}
void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
llvm::FunctionCallee dtor,
@@ -570,7 +560,7 @@ class XLCXXABI final : public ItaniumCXXABI {
void emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub,
llvm::Constant *addr);
};
-}
+} // namespace
CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
switch (CGM.getContext().getCXXABIKind()) {
@@ -641,8 +631,8 @@ ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
/// the function to call.
CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
CodeGenFunction &CGF, const Expr *E, Address ThisAddr,
- llvm::Value *&ThisPtrForCall,
- llvm::Value *MemFnPtr, const MemberPointerType *MPT) {
+ llvm::Value *&ThisPtrForCall, llvm::Value *MemFnPtr,
+ const MemberPointerType *MPT) {
CGBuilderTy &Builder = CGF.Builder;
const FunctionProtoType *FPT =
@@ -689,9 +679,8 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
// Cast the adjusted this to a pointer to vtable pointer and load.
llvm::Type *VTableTy = CGF.CGM.GlobalsInt8PtrTy;
- CharUnits VTablePtrAlign =
- CGF.CGM.getDynamicOffsetAlignment(ThisAddr.getAlignment(), RD,
- CGF.getPointerAlign());
+ CharUnits VTablePtrAlign = CGF.CGM.getDynamicOffsetAlignment(
+ ThisAddr.getAlignment(), RD, CGF.getPointerAlign());
llvm::Value *VTable = CGF.GetVTablePtr(
Address(This, ThisAddr.getElementType(), VTablePtrAlign), VTableTy, RD);
@@ -953,10 +942,9 @@ static llvm::Constant *pointerAuthResignConstant(
/// MP when the derived MP does not point to a member of the base.
/// This is why -1 is a reasonable choice for null data member
/// pointers.
-llvm::Value *
-ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
- const CastExpr *E,
- llvm::Value *src) {
+llvm::Value *ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
+ const CastExpr *E,
+ llvm::Value *src) {
// Use constant emission if we can.
if (isa<llvm::Constant>(src))
return EmitMemberPointerConversion(E, cast<llvm::Constant>(src));
@@ -1009,15 +997,16 @@ ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
}
// Under Itanium, reinterprets don't require any additional processing.
- if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;
+ if (E->getCastKind() == CK_ReinterpretMemberPointer)
+ return src;
llvm::Constant *adj = getMemberPointerAdjustment(E);
- if (!adj) return src;
+ if (!adj)
+ return src;
bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
- const MemberPointerType *destTy =
- E->getType()->castAs<MemberPointerType>();
+ const MemberPointerType *destTy = E->getType()->castAs<MemberPointerType>();
// For member data pointers, this is just a matter of adding the
// offset if the source is non-null.
@@ -1093,22 +1082,24 @@ ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E,
src, DstType, E->getSubExpr()->getType(), CGM);
// Under Itanium, reinterprets don't require any additional processing.
- if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;
+ if (E->getCastKind() == CK_ReinterpretMemberPointer)
+ return src;
// If the adjustment is trivial, we don't need to do anything.
llvm::Constant *adj = getMemberPointerAdjustment(E);
- if (!adj) return src;
+ if (!adj)
+ return src;
bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
- const MemberPointerType *destTy =
- E->getType()->castAs<MemberPointerType>();
+ const MemberPointerType *destTy = E->getType()->castAs<MemberPointerType>();
// For member data pointers, this is just a matter of adding the
// offset if the source is non-null.
if (destTy->isMemberDataPointer()) {
// null maps to null.
- if (src->isAllOnesValue()) return src;
+ if (src->isAllOnesValue())
+ return src;
if (isDerivedToBase)
return llvm::ConstantExpr::getNSWSub(src, adj);
@@ -1143,7 +1134,7 @@ ItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL, /*isSigned=*/true);
llvm::Constant *Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0);
- llvm::Constant *Values[2] = { Zero, Zero };
+ llvm::Constant *Values[2] = {Zero, Zero};
return llvm::ConstantStruct::getAnon(Values);
}
@@ -1221,8 +1212,8 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
// virtual table offset (in bytes) of the function,
// represented as a ptrdiff_t.
MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset + 1);
- MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
- ThisAdjustment.getQuantity());
+ MemPtr[1] =
+ llvm::ConstantInt::get(CGM.PtrDiffTy, ThisAdjustment.getQuantity());
}
} else {
const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
@@ -1239,9 +1230,9 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
llvm::Constant *addr = CGM.getMemberFunctionPointer(MD, Ty);
MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy);
- MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
- (UseARMMethodPtrABI ? 2 : 1) *
- ThisAdjustment.getQuantity());
+ MemPtr[1] =
+ llvm::ConstantInt::get(CGM.PtrDiffTy, (UseARMMethodPtrABI ? 2 : 1) *
+ ThisAdjustment.getQuantity());
}
return llvm::ConstantStruct::getAnon(MemPtr);
@@ -1265,7 +1256,7 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP,
getContext().recordMemberDataPointerEvaluation(MPD);
CharUnits FieldOffset =
- getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
+ getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset);
}
@@ -1273,12 +1264,9 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP,
/// the same if they're either bitwise identical *or* both null.
///
/// ARM is different here only because null-ness is more complicated.
-llvm::Value *
-ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
- llvm::Value *L,
- llvm::Value *R,
- const MemberPointerType *MPT,
- bool Inequality) {
+llvm::Value *ItaniumCXXABI::EmitMemberPointerComparison(
+ CodeGenFunction &CGF, llvm::Value *L, llvm::Value *R,
+ const MemberPointerType *MPT, bool Inequality) {
CGBuilderTy &Builder = CGF.Builder;
llvm::ICmpInst::Predicate Eq;
@@ -1335,8 +1323,8 @@ ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
// Compute (l.adj | r.adj) & 1 and test it against zero.
llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj");
llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One);
- llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero,
- "cmp.or.adj");
+ llvm::Value *OrAdjAnd1EqZero =
+ Builder.CreateICmp(Eq, OrAdjAnd1, Zero, "cmp.or.adj");
EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero);
}
@@ -1347,17 +1335,15 @@ ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
return Result;
}
-llvm::Value *
-ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
- llvm::Value *MemPtr,
- const MemberPointerType *MPT) {
+llvm::Value *ItaniumCXXABI::EmitMemberPointerIsNotNull(
+ CodeGenFunction &CGF, llvm::Value *MemPtr, const MemberPointerType *MPT) {
CGBuilderTy &Builder = CGF.Builder;
/// For member data pointers, this is just a check against -1.
if (MPT->isMemberDataPointer()) {
assert(MemPtr->getType() == CGM.PtrDiffTy);
llvm::Value *NegativeOne =
- llvm::Constant::getAllOnesValue(MemPtr->getType());
+ llvm::Constant::getAllOnesValue(MemPtr->getType());
return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool");
}
@@ -1373,8 +1359,8 @@ ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj");
llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit");
- llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero,
- "memptr.isvirtual");
+ llvm::Value *IsVirtual =
+ Builder.CreateICmpNE(VirtualBit, Zero, "memptr.isvirtual");
Result = Builder.CreateOr(Result, IsVirtual);
}
@@ -1409,8 +1395,7 @@ bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
/// at entry -2 in the vtable.
void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
const CXXDeleteExpr *DE,
- Address Ptr,
- QualType ElementType,
+ Address Ptr, QualType ElementType,
const CXXDestructorDecl *Dtor) {
bool UseGlobalDelete = DE->isGlobalDelete();
if (UseGlobalDelete) {
@@ -1452,7 +1437,7 @@ void ItaniumCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) {
// void __cxa_rethrow();
llvm::FunctionType *FTy =
- llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+ llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
llvm::FunctionCallee Fn = CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow");
@@ -1466,7 +1451,7 @@ static llvm::FunctionCallee getAllocateExceptionFn(CodeGenModule &CGM) {
// void *__cxa_allocate_exception(size_t thrown_size);
llvm::FunctionType *FTy =
- llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, /*isVarArg=*/false);
+ llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, /*isVarArg=*/false);
return CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception");
}
@@ -1475,9 +1460,9 @@ static llvm::FunctionCallee getThrowFn(CodeGenModule &CGM) {
// void __cxa_throw(void *thrown_exception, std::type_info *tinfo,
// void (*dest) (void *));
- llvm::Type *Args[3] = { CGM.Int8PtrTy, CGM.GlobalsInt8PtrTy, CGM.Int8PtrTy };
+ llvm::Type *Args[3] = {CGM.Int8PtrTy, CGM.GlobalsInt8PtrTy, CGM.Int8PtrTy};
llvm::FunctionType *FTy =
- llvm::FunctionType::get(CGM.VoidTy, Args, /*isVarArg=*/false);
+ llvm::FunctionType::get(CGM.VoidTy, Args, /*isVarArg=*/false);
return CGM.CreateRuntimeFunction(FTy, "__cxa_throw");
}
@@ -1493,8 +1478,8 @@ void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize), "exception");
CharUnits ExnAlign = CGF.getContext().getExnObjectAlignment();
- CGF.EmitAnyExprToExn(
- E->getSubExpr(), Address(ExceptionPtr, CGM.Int8Ty, ExnAlign));
+ CGF.EmitAnyExprToExn(E->getSubExpr(),
+ Address(ExceptionPtr, CGM.Int8Ty, ExnAlign));
// Now throw the exception.
llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,
@@ -1516,9 +1501,10 @@ void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
Dtor = CGM.getAddrOfCXXStructor(GlobalDecl(DtorD, Dtor_Complete));
Dtor = CGM.getFunctionPointer(Dtor, DtorTy);
}
- if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
+ if (!Dtor)
+ Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
- llvm::Value *args[] = { ExceptionPtr, TypeInfo, Dtor };
+ llvm::Value *args[] = {ExceptionPtr, TypeInfo, Dtor};
CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(CGM), args);
}
@@ -1531,9 +1517,9 @@ static llvm::FunctionCallee getItaniumDynamicCastFn(CodeGenFunction &CGF) {
llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
llvm::Type *GlobInt8PtrTy = CGF.GlobalsInt8PtrTy;
llvm::Type *PtrDiffTy =
- CGF.ConvertType(CGF.getContext().getPointerDiffType());
+ CGF.ConvertType(CGF.getContext().getPointerDiffType());
- llvm::Type *Args[4] = { Int8PtrTy, GlobInt8PtrTy, GlobInt8PtrTy, PtrDiffTy };
+ llvm::Type *Args[4] = {Int8PtrTy, GlobInt8PtrTy, GlobInt8PtrTy, PtrDiffTy};
llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
@@ -1572,7 +1558,7 @@ static CharUnits computeOffsetHint(ASTContext &Context,
// Now walk all possible inheritance paths.
for (const CXXBasePath &Path : Paths) {
- if (Path.Access != AS_public) // Ignore non-public inheritance.
+ if (Path.Access != AS_public) // Ignore non-public inheritance.
continue;
++NumPublicPaths;
@@ -1625,12 +1611,11 @@ void ItaniumCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
}
llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,
- QualType SrcRecordTy,
- Address ThisPtr,
+ QualType SrcRecordTy, Address ThisPtr,
llvm::Type *StdTypeInfoPtrTy) {
auto *ClassDecl = SrcRecordTy->castAsCXXRecordDecl();
- llvm::Value *Value = CGF.GetVTablePtr(ThisPtr, CGM.GlobalsInt8PtrTy,
- ClassDecl);
+ llvm::Value *Value =
+ CGF.GetVTablePtr(ThisPtr, CGM.GlobalsInt8PtrTy, ClassDecl);
if (CGM.getLangOpts().RelativeCXXABIVTables) {
// Load the type info.
@@ -1879,24 +1864,22 @@ bool ItaniumCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
}
llvm::Value *
-ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
- Address This,
+ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This,
const CXXRecordDecl *ClassDecl,
const CXXRecordDecl *BaseClassDecl) {
llvm::Value *VTablePtr = CGF.GetVTablePtr(This, CGM.Int8PtrTy, ClassDecl);
CharUnits VBaseOffsetOffset =
CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,
BaseClassDecl);
- llvm::Value *VBaseOffsetPtr =
- CGF.Builder.CreateConstGEP1_64(
- CGF.Int8Ty, VTablePtr, VBaseOffsetOffset.getQuantity(),
- "vbase.offset.ptr");
+ llvm::Value *VBaseOffsetPtr = CGF.Builder.CreateConstGEP1_64(
+ CGF.Int8Ty, VTablePtr, VBaseOffsetOffset.getQuantity(),
+ "vbase.offset.ptr");
llvm::Value *VBaseOffset;
if (CGM.getLangOpts().RelativeCXXABIVTables) {
- VBaseOffset = CGF.Builder.CreateAlignedLoad(
- CGF.Int32Ty, VBaseOffsetPtr, CharUnits::fromQuantity(4),
- "vbase.offset");
+ VBaseOffset = CGF.Builder.CreateAlignedLoad(CGF.Int32Ty, VBaseOffsetPtr,
+ CharUnits::fromQuantity(4),
+ "vbase.offset");
} else {
VBaseOffset = CGF.Builder.CreateAlignedLoad(
CGM.PtrDiffTy, VBaseOffsetPtr, CGF.getPointerAlign(), "vbase.offset");
@@ -2041,8 +2024,8 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
CGCallee Callee;
- if (getContext().getLangOpts().AppleKext &&
- Type != Dtor_Base && DD->isVirtual())
+ if (getContext().getLangOpts().AppleKext && Type != Dtor_Base &&
+ DD->isVirtual())
Callee = CGF.BuildAppleKextVirtualDestructorCall(DD, Type, DD->getParent());
else
Callee = CGCallee::forDirect(CGM.getAddrOfCXXStructor(GD), GD);
@@ -2192,9 +2175,9 @@ ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
VTableLayout::AddressPointLocation AddressPoint =
Layout.getAddressPoint(Base);
llvm::Value *Indices[] = {
- llvm::ConstantInt::get(CGM.Int32Ty, 0),
- llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex),
- llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex),
+ llvm::ConstantInt::get(CGM.Int32Ty, 0),
+ llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex),
+ llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex),
};
// Add inrange attribute to indicate that only the VTableIndex can be
@@ -2228,13 +2211,15 @@ llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
VirtualPointerIndex);
// And load the address point from the VTT.
- llvm::Value *AP =
- CGF.Builder.CreateAlignedLoad(CGF.GlobalsVoidPtrTy, VTT,
- CGF.getPointerAlign());
-
- if (auto PointerAuth = CGM.getVTablePointerAuthInfo(&CGF, VTableClass, VTT,
- /*IsVTTEntry=*/true))
- AP = CGF.EmitPointerAuthAuth(*PointerAuth, AP);
+ llvm::Value *AP = CGF.Builder.CreateAlignedLoad(CGF.GlobalsVoidPtrTy, VTT,
+ CGF.getPointerAlign());
+
+ if (auto &Schema =
+ CGF.CGM.getCodeGenOpts().PointerAuth.CXXVTTVTablePointers) {
+ CGPointerAuthInfo PointerAuth =
+ CGF.EmitPointerAuthInfo(Schema, VTT, GlobalDecl(), QualType());
+ AP = CGF.EmitPointerAuthAuth(PointerAuth, AP);
+ }
return AP;
}
@@ -2277,8 +2262,7 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
}
CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
- GlobalDecl GD,
- Address This,
+ GlobalDecl GD, Address This,
llvm::Type *Ty,
SourceLocation Loc) {
llvm::Type *PtrTy = CGM.GlobalsInt8PtrTy;
@@ -2350,8 +2334,10 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
CGPointerAuthInfo PointerAuth;
if (Schema) {
assert(VTableSlotPtr && "virtual function pointer not set");
- GD = CGM.getItaniumVTableContext().findOriginalMethod(GD.getCanonicalDecl());
- PointerAuth = CGF.EmitPointerAuthInfo(Schema, VTableSlotPtr, GD, QualType());
+ GD =
+ CGM.getItaniumVTableContext().findOriginalMethod(GD.getCanonicalDecl());
+ PointerAuth =
+ CGF.EmitPointerAuthInfo(Schema, VTableSlotPtr, GD, QualType());
}
CGCallee Callee(GD, VFunc, PointerAuth);
return Callee;
@@ -2473,8 +2459,8 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
// In a base-to-derived cast, the non-virtual adjustment is applied first.
if (NonVirtualAdjustment && !IsReturnAdjustment) {
- V = CGF.Builder.CreateConstInBoundsByteGEP(V,
- CharUnits::fromQuantity(NonVirtualAdjustment));
+ V = CGF.Builder.CreateConstInBoundsByteGEP(
+ V, CharUnits::fromQuantity(NonVirtualAdjustment));
}
// Perform the virtual adjustment if we have one.
@@ -2488,9 +2474,8 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
CGF.Int8Ty, VTablePtr, VirtualAdjustment);
if (CGF.CGM.getLangOpts().RelativeCXXABIVTables) {
// Load the adjustment offset from the vtable as a 32-bit int.
- Offset =
- CGF.Builder.CreateAlignedLoad(CGF.Int32Ty, OffsetPtr,
- CharUnits::fromQuantity(4));
+ Offset = CGF.Builder.CreateAlignedLoad(CGF.Int32Ty, OffsetPtr,
+ CharUnits::fromQuantity(4));
} else {
llvm::Type *PtrDiffTy =
CGF.ConvertType(CGF.getContext().getPointerDiffType());
@@ -2534,8 +2519,8 @@ ItaniumCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
/*IsReturnAdjustment=*/true);
}
-void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
- RValue RV, QualType ResultType) {
+void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV,
+ QualType ResultType) {
if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl()))
return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType);
@@ -2606,8 +2591,8 @@ llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
Address numElementsPtr = allocPtr;
CharUnits numElementsOffset = cookieSize - CGF.getSizeSize();
if (!numElementsOffset.isZero())
- numElementsPtr =
- CGF.Builder.CreateConstInBoundsByteGEP(numElementsPtr, numElementsOffset);
+ numElementsPtr = CGF.Builder.CreateConstInBoundsByteGEP(numElementsPtr,
+ numElementsOffset);
unsigned AS = allocPtr.getAddressSpace();
numElementsPtr = numElementsPtr.withElementType(CGF.SizeTy);
@@ -2638,8 +2623,7 @@ CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {
CGM.getContext().getTypeAlignInChars(elementType));
}
-Address ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
- Address newPtr,
+Address ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, Address newPtr,
llvm::Value *numElements,
const CXXNewExpr *expr,
QualType elementType) {
@@ -2650,8 +2634,8 @@ Address ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
// The first element is the element size.
cookie = cookie.withElementType(CGF.SizeTy);
- llvm::Value *elementSize = llvm::ConstantInt::get(CGF.SizeTy,
- getContext().getTypeSizeInChars(elementType).getQuantity());
+ llvm::Value *elementSize = llvm::ConstantInt::get(
+ CGF.SizeTy, getContext().getTypeSizeInChars(elementType).getQuantity());
CGF.Builder.CreateStore(elementSize, cookie);
// The second element is the element count.
@@ -2669,8 +2653,8 @@ llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
CharUnits cookieSize) {
// The number of elements is at offset sizeof(size_t) relative to
// the allocated pointer.
- Address numElementsPtr
- = CGF.Builder.CreateConstInBoundsByteGEP(allocPtr, CGF.getSizeSize());
+ Address numElementsPtr =
+ CGF.Builder.CreateConstInBoundsByteGEP(allocPtr, CGF.getSizeSize());
numElementsPtr = numElementsPtr.withElementType(CGF.SizeTy);
return CGF.Builder.CreateLoad(numElementsPtr);
@@ -2681,9 +2665,9 @@ llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
static llvm::FunctionCallee getGuardAcquireFn(CodeGenModule &CGM,
llvm::PointerType *GuardPtrTy) {
// int __cxa_guard_acquire(__guard *guard_object);
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy),
- GuardPtrTy, /*isVarArg=*/false);
+ llvm::FunctionType *FTy = llvm::FunctionType::get(
+ CGM.getTypes().ConvertType(CGM.getContext().IntTy), GuardPtrTy,
+ /*isVarArg=*/false);
return CGM.CreateRuntimeFunction(
FTy, "__cxa_guard_acquire",
llvm::AttributeList::get(CGM.getLLVMContext(),
@@ -2695,7 +2679,7 @@ static llvm::FunctionCallee getGuardReleaseFn(CodeGenModule &CGM,
llvm::PointerType *GuardPtrTy) {
// void __cxa_guard_release(__guard *guard_object);
llvm::FunctionType *FTy =
- llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false);
+ llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false);
return CGM.CreateRuntimeFunction(
FTy, "__cxa_guard_release",
llvm::AttributeList::get(CGM.getLLVMContext(),
@@ -2707,7 +2691,7 @@ static llvm::FunctionCallee getGuardAbortFn(CodeGenModule &CGM,
llvm::PointerType *GuardPtrTy) {
// void __cxa_guard_abort(__guard *guard_object);
llvm::FunctionType *FTy =
- llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false);
+ llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false);
return CGM.CreateRuntimeFunction(
FTy, "__cxa_guard_abort",
llvm::AttributeList::get(CGM.getLLVMContext(),
@@ -2716,21 +2700,20 @@ static llvm::FunctionCallee getGuardAbortFn(CodeGenModule &CGM,
}
namespace {
- struct CallGuardAbort final : EHScopeStack::Cleanup {
- llvm::GlobalVariable *Guard;
- CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
+struct CallGuardAbort final : EHScopeStack::Cleanup {
+ llvm::GlobalVariable *Guard;
+ CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- CGF.EmitNounwindRuntimeCall(getGuardAbortFn(CGF.CGM, Guard->getType()),
- Guard);
- }
- };
-}
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ CGF.EmitNounwindRuntimeCall(getGuardAbortFn(CGF.CGM, Guard->getType()),
+ Guard);
+ }
+};
+} // namespace
/// The ARM code here follows the Itanium code closely enough that we
/// just special-case it at particular places.
-void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
- const VarDecl &D,
+void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
llvm::GlobalVariable *var,
bool shouldPerformInit) {
CGBuilderTy &Builder = CGF.Builder;
@@ -2787,10 +2770,9 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
// Create the guard variable with a zero-initializer.
// Just absorb linkage, visibility and dll storage class from the guarded
// variable.
- guard = new llvm::GlobalVariable(CGM.getModule(), guardTy,
- false, var->getLinkage(),
- llvm::ConstantInt::get(guardTy, 0),
- guardName.str());
+ guard = new llvm::GlobalVariable(
+ CGM.getModule(), guardTy, false, var->getLinkage(),
+ llvm::ConstantInt::get(guardTy, 0), guardName.str());
guard->setDSOLocal(var->isDSOLocal());
guard->setVisibility(var->getVisibility());
guard->setDLLStorageClass(var->getDLLStorageClass());
@@ -2870,8 +2852,8 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
//
// ARM64 C++ ABI 3.2.2:
// This ABI instead only specifies the value bit 0 of the static guard
- // variable; all other bits are platform defined. Bit 0 shall be 0 when the
- // variable is not initialized and 1 when it is.
+ // variable; all other bits are platform defined. Bit 0 shall be 0 when
+ // the variable is not initialized and 1 when it is.
llvm::Value *V =
(UseARMGuardVarABI && !useInt8GuardVariable)
? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1))
@@ -2905,13 +2887,13 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
// Variables used when coping with thread-safe statics and exceptions.
if (threadsafe) {
// Call __cxa_guard_acquire.
- llvm::Value *V
- = CGF.EmitNounwindRuntimeCall(getGuardAcquireFn(CGM, guardPtrTy), guard);
+ llvm::Value *V =
+ CGF.EmitNounwindRuntimeCall(getGuardAcquireFn(CGM, guardPtrTy), guard);
llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
- Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
- InitBlock, EndBlock);
+ Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), InitBlock,
+ EndBlock);
// Call __cxa_guard_abort along the exceptional edge.
CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, guard);
@@ -2957,7 +2939,7 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF,
const char *Name = "__cxa_atexit";
if (TLS) {
const llvm::Triple &T = CGF.getTarget().getTriple();
- Name = T.isOSDarwin() ? "_tlv_atexit" : "__cxa_thread_atexit";
+ Name = T.isOSDarwin() ? "_tlv_atexit" : "__cxa_thread_atexit";
}
// We're assuming that the destructor function is something we can
@@ -2978,7 +2960,7 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF,
// extern "C" int __cxa_atexit(void (*f)(void *), void *p, void *d);
llvm::Type *paramTys[] = {dtorTy, AddrPtrTy, handle->getType()};
llvm::FunctionType *atexitTy =
- llvm::FunctionType::get(CGF.IntTy, paramTys, false);
+ llvm::FunctionType::get(CGF.IntTy, paramTys, false);
// Fetch the actual function.
llvm::FunctionCallee atexit = CGF.CGM.CreateRuntimeFunction(atexitTy, Name);
@@ -3131,7 +3113,18 @@ void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
// destructors which we can handle directly in the runtime. Note that this is
// not strictly 1-to-1 with using `atexit` because we no longer tear down
// globals in reverse order of when they were constructed.
- if (!CGM.getLangOpts().hasAtExit() && !D.isStaticLocal())
+
+ // If '-fno-use-cxa-atexit' and '-fno-register-global-dtors-with-atexit' are
+ // also sepcified, this means the user does not want any invocation to
+ // __cxa_atexit or atexit, but we still have to check if the declaration is
+ // static-local or thread-local, which should not be supported by this case.
+ // As we investigated, ELF has its .fini_array section to support the global
+ // destructors. So we can safely apply this to ELF.
+ if (!CGM.getLangOpts().hasAtExit() &&
+ CGM.getTarget().getTriple().isOSBinFormatELF() &&
+ !CGM.getCodeGenOpts().CXAAtExit &&
+ !CGM.getCodeGenOpts().RegisterGlobalDtorsWithAtExit &&
+ !D.isStaticLocal() && !D.getTLSKind())
return CGF.registerGlobalDtorWithLLVM(D, dtor, addr);
// emitGlobalDtorWithCXAAtExit will emit a call to either __cxa_thread_atexit
@@ -3180,9 +3173,8 @@ getThreadLocalWrapperLinkage(const VarDecl *VD, CodeGen::CodeGenModule &CGM) {
return llvm::GlobalValue::WeakODRLinkage;
}
-llvm::Function *
-ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD,
- llvm::Value *Val) {
+llvm::Function *ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD,
+ llvm::Value *Val) {
// Mangle the name for the thread_local wrapper function.
SmallString<256> WrapperName;
{
@@ -3362,8 +3354,7 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
// This is needed whenever a thread wrapper function is not used, and
// also when the symbol is weak.
if (CGM.getTriple().isOSAIX() && VD->hasDefinition() &&
- isEmittedWithConstantInitializer(VD, true) &&
- !mayNeedDestruction(VD)) {
+ isEmittedWithConstantInitializer(VD, true) && !mayNeedDestruction(VD)) {
// Init should be null. If it were non-null, then the logic above would
// either be defining the function to be an alias or declaring the
// function with the expectation that the definition of the variable
@@ -3551,9 +3542,9 @@ ItaniumCXXABI::getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD) {
namespace {
class ItaniumRTTIBuilder {
- CodeGenModule &CGM; // Per-module state.
+ CodeGenModule &CGM; // Per-module state.
llvm::LLVMContext &VMContext;
- const ItaniumCXXABI &CXXABI; // Per-module state.
+ const ItaniumCXXABI &CXXABI; // Per-module state.
/// Fields - The fields of the RTTI descriptor currently being built.
SmallVector<llvm::Constant *, 16> Fields;
@@ -3613,7 +3604,7 @@ class ItaniumRTTIBuilder {
PTI_ContainingClassIncomplete = 0x10,
/// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).
- //PTI_TransactionSafe = 0x20,
+ // PTI_TransactionSafe = 0x20,
/// PTI_Noexcept - Pointee is noexcept function (C++1z).
PTI_Noexcept = 0x40,
@@ -3642,13 +3633,12 @@ class ItaniumRTTIBuilder {
llvm::Constant *BuildTypeInfo(QualType Ty);
/// BuildTypeInfo - Build the RTTI type info struct for the given type.
- llvm::Constant *BuildTypeInfo(
- QualType Ty,
- llvm::GlobalVariable::LinkageTypes Linkage,
- llvm::GlobalValue::VisibilityTypes Visibility,
- llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);
+ llvm::Constant *
+ BuildTypeInfo(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage,
+ llvm::GlobalValue::VisibilityTypes Visibility,
+ llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);
};
-}
+} // namespace
llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(
QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage) {
@@ -3731,53 +3721,50 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
// 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;
+ 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:
+#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:
+#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:
+ 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:
+#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"
@@ -3818,8 +3805,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
case BuiltinType::Dependent:
#define BUILTIN_TYPE(Id, SingletonId)
-#define PLACEHOLDER_TYPE(Id, SingletonId) \
- case BuiltinType::Id:
+#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
#include "clang/AST/BuiltinTypes.def"
llvm_unreachable("asking for RRTI for a placeholder type!");
@@ -3827,7 +3813,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
case BuiltinType::ObjCClass:
case BuiltinType::ObjCSel:
llvm_unreachable("FIXME: Objective-C types are unsupported!");
- }
+ }
llvm_unreachable("Invalid BuiltinType Kind!");
}
@@ -3867,13 +3853,13 @@ static bool IsStandardLibraryRTTIDescriptor(QualType Ty) {
/// 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
/// standard-library type.
-static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM,
- QualType Ty) {
+static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, QualType Ty) {
ASTContext &Context = CGM.getContext();
// If RTTI is disabled, assume it might be disabled in the
// translation unit that defines any potential key function, too.
- if (!Context.getLangOpts().RTTI) return false;
+ if (!Context.getLangOpts().RTTI)
+ return false;
if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
const CXXRecordDecl *RD =
@@ -3935,7 +3921,7 @@ static bool ContainsIncompleteClassType(QualType Ty) {
return ContainsIncompleteClassType(PointerTy->getPointeeType());
if (const MemberPointerType *MemberPointerTy =
- dyn_cast<MemberPointerType>(Ty)) {
+ dyn_cast<MemberPointerType>(Ty)) {
// Check if the class type is incomplete.
if (!MemberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())
return true;
@@ -3977,14 +3963,14 @@ static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty,
llvm::Constant *StorageAddress) {
// abi::__class_type_info.
- static const char * const ClassTypeInfo =
- "_ZTVN10__cxxabiv117__class_type_infoE";
+ 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";
+ 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";
+ static const char *const VMIClassTypeInfo =
+ "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
const char *VTableName = nullptr;
@@ -4238,10 +4224,9 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) {
}
llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
- QualType Ty,
- llvm::GlobalVariable::LinkageTypes Linkage,
- llvm::GlobalValue::VisibilityTypes Visibility,
- llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {
+ QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage,
+ llvm::GlobalValue::VisibilityTypes Visibility,
+ llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {
SmallString<256> Name;
llvm::raw_svector_ostream Out(Name);
CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
@@ -4443,13 +4428,15 @@ void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
// The builtin types are abi::__class_type_infos and don't require
// extra fields.
- if (isa<BuiltinType>(T)) return;
+ if (isa<BuiltinType>(T))
+ return;
ObjCInterfaceDecl *Class = cast<ObjCInterfaceType>(T)->getDecl();
ObjCInterfaceDecl *Super = Class->getSuperClass();
// Root classes are also __class_type_info.
- if (!Super) return;
+ if (!Super)
+ return;
QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super);
@@ -4466,18 +4453,18 @@ void ItaniumRTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
// It adds to abi::__class_type_info a single member pointing to the
// type_info structure for the base type,
llvm::Constant *BaseTypeInfo =
- ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(RD->bases_begin()->getType());
+ ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(RD->bases_begin()->getType());
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;
- };
-}
+/// 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;
+};
+} // namespace
/// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in
/// abi::__vmi_class_type_info.
@@ -4533,7 +4520,7 @@ static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {
/// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
llvm::Type *UnsignedIntLTy =
- CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+ CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
// Itanium C++ ABI 2.9.5p6c:
// __flags is a word with flags describing details about the class
@@ -4578,8 +4565,7 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
if (TI.getTriple().isOSCygMing() &&
TI.getPointerWidth(LangAS::Default) > TI.getLongWidth())
OffsetFlagsTy = CGM.getContext().LongLongTy;
- llvm::Type *OffsetFlagsLTy =
- CGM.getTypes().ConvertType(OffsetFlagsTy);
+ llvm::Type *OffsetFlagsLTy = CGM.getTypes().ConvertType(OffsetFlagsTy);
for (const auto &Base : RD->bases()) {
// The __base_type member points to the RTTI for the base type.
@@ -4594,8 +4580,8 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
// the virtual base offset for the virtual base referenced (negative).
CharUnits Offset;
if (Base.isVirtual())
- Offset =
- CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl);
+ Offset = CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(
+ RD, BaseDecl);
else {
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
Offset = Layout.getBaseClassOffset(BaseDecl);
@@ -4652,7 +4638,7 @@ void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy);
llvm::Type *UnsignedIntLTy =
- CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+ CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
// Itanium C++ ABI 2.9.5p7:
@@ -4665,8 +4651,8 @@ void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
/// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
/// struct, used for member pointer types.
-void
-ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
+void ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(
+ const MemberPointerType *Ty) {
QualType PointeeTy = Ty->getPointeeType();
// Itanium C++ ABI 2.9.5p7:
@@ -4679,7 +4665,7 @@ ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
Flags |= PTI_ContainingClassIncomplete;
llvm::Type *UnsignedIntLTy =
- CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+ CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
// Itanium C++ ABI 2.9.5p7:
@@ -4703,21 +4689,31 @@ llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) {
void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) {
// Types added here must also be added to TypeInfoIsInStandardLibrary.
- QualType FundamentalTypes[] = {
- getContext().VoidTy, getContext().NullPtrTy,
- getContext().BoolTy, getContext().WCharTy,
- getContext().CharTy, getContext().UnsignedCharTy,
- getContext().SignedCharTy, getContext().ShortTy,
- getContext().UnsignedShortTy, getContext().IntTy,
- getContext().UnsignedIntTy, getContext().LongTy,
- getContext().UnsignedLongTy, getContext().LongLongTy,
- getContext().UnsignedLongLongTy, getContext().Int128Ty,
- getContext().UnsignedInt128Ty, getContext().HalfTy,
- getContext().FloatTy, getContext().DoubleTy,
- getContext().LongDoubleTy, getContext().Float128Ty,
- getContext().Char8Ty, getContext().Char16Ty,
- getContext().Char32Ty
- };
+ QualType FundamentalTypes[] = {getContext().VoidTy,
+ getContext().NullPtrTy,
+ getContext().BoolTy,
+ getContext().WCharTy,
+ getContext().CharTy,
+ getContext().UnsignedCharTy,
+ getContext().SignedCharTy,
+ getContext().ShortTy,
+ getContext().UnsignedShortTy,
+ getContext().IntTy,
+ getContext().UnsignedIntTy,
+ getContext().LongTy,
+ getContext().UnsignedLongTy,
+ getContext().LongLongTy,
+ getContext().UnsignedLongLongTy,
+ getContext().Int128Ty,
+ getContext().UnsignedInt128Ty,
+ getContext().HalfTy,
+ getContext().FloatTy,
+ getContext().DoubleTy,
+ getContext().LongDoubleTy,
+ getContext().Float128Ty,
+ getContext().Char8Ty,
+ getContext().Char16Ty,
+ getContext().Char32Ty};
llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
RD->hasAttr<DLLExportAttr>() || CGM.shouldMapVisibilityToDLLExport(RD)
? llvm::GlobalValue::DLLExportStorageClass
@@ -4726,12 +4722,12 @@ void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) {
CodeGenModule::GetLLVMVisibility(RD->getVisibility());
for (const QualType &FundamentalType : FundamentalTypes) {
QualType PointerType = getContext().getPointerType(FundamentalType);
- QualType PointerTypeConst = getContext().getPointerType(
- FundamentalType.withConst());
+ QualType PointerTypeConst =
+ getContext().getPointerType(FundamentalType.withConst());
for (QualType Type : {FundamentalType, PointerType, PointerTypeConst})
ItaniumRTTIBuilder(*this).BuildTypeInfo(
- Type, llvm::GlobalValue::ExternalLinkage,
- Visibility, DLLStorageClass);
+ Type, llvm::GlobalValue::ExternalLinkage, Visibility,
+ DLLStorageClass);
}
}
@@ -4903,8 +4899,8 @@ void ItaniumCXXABI::emitCXXStructor(GlobalDecl GD) {
static llvm::FunctionCallee getBeginCatchFn(CodeGenModule &CGM) {
// void *__cxa_begin_catch(void*);
- llvm::FunctionType *FTy = llvm::FunctionType::get(
- CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false);
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false);
return CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch");
}
@@ -4919,39 +4915,39 @@ static llvm::FunctionCallee getEndCatchFn(CodeGenModule &CGM) {
static llvm::FunctionCallee getGetExceptionPtrFn(CodeGenModule &CGM) {
// void *__cxa_get_exception_ptr(void*);
- llvm::FunctionType *FTy = llvm::FunctionType::get(
- CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false);
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false);
return CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr");
}
namespace {
- /// A cleanup to call __cxa_end_catch. In many cases, the caught
- /// exception type lets us state definitively that the thrown exception
- /// type does not have a destructor. In particular:
- /// - Catch-alls tell us nothing, so we have to conservatively
- /// assume that the thrown exception might have a destructor.
- /// - Catches by reference behave according to their base types.
- /// - Catches of non-record types will only trigger for exceptions
- /// of non-record types, which never have destructors.
- /// - Catches of record types can trigger for arbitrary subclasses
- /// of the caught type, so we have to assume the actual thrown
- /// exception type might have a throwing destructor, even if the
- /// caught type's destructor is trivial or nothrow.
- struct CallEndCatch final : EHScopeStack::Cleanup {
- CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}
- bool MightThrow;
-
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- if (!MightThrow) {
- CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM));
- return;
- }
-
- CGF.EmitRuntimeCallOrInvoke(getEndCatchFn(CGF.CGM));
+/// A cleanup to call __cxa_end_catch. In many cases, the caught
+/// exception type lets us state definitively that the thrown exception
+/// type does not have a destructor. In particular:
+/// - Catch-alls tell us nothing, so we have to conservatively
+/// assume that the thrown exception might have a destructor.
+/// - Catches by reference behave according to their base types.
+/// - Catches of non-record types will only trigger for exceptions
+/// of non-record types, which never have destructors.
+/// - Catches of record types can trigger for arbitrary subclasses
+/// of the caught type, so we have to assume the actual thrown
+/// exception type might have a throwing destructor, even if the
+/// caught type's destructor is trivial or nothrow.
+struct CallEndCatch final : EHScopeStack::Cleanup {
+ CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}
+ bool MightThrow;
+
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ if (!MightThrow) {
+ CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM));
+ return;
}
- };
-}
+
+ CGF.EmitRuntimeCallOrInvoke(getEndCatchFn(CGF.CGM));
+ }
+};
+} // namespace
/// Emits a call to __cxa_begin_catch and enters a cleanup to call
/// __cxa_end_catch. If -fassume-nothrow-exception-dtor is specified, we assume
@@ -4959,11 +4955,10 @@ namespace {
/// call can be marked as nounwind even if EndMightThrow is true.
///
/// \param EndMightThrow - true if __cxa_end_catch might throw
-static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,
- llvm::Value *Exn,
+static llvm::Value *CallBeginCatch(CodeGenFunction &CGF, llvm::Value *Exn,
bool EndMightThrow) {
llvm::CallInst *call =
- CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn);
+ CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn);
CGF.EHStack.pushCleanup<CallEndCatch>(
NormalAndEHCleanup,
@@ -4974,15 +4969,13 @@ static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,
/// A "special initializer" callback for initializing a catch
/// parameter during catch initialization.
-static void InitCatchParam(CodeGenFunction &CGF,
- const VarDecl &CatchParam,
- Address ParamAddr,
- SourceLocation Loc) {
+static void InitCatchParam(CodeGenFunction &CGF, const VarDecl &CatchParam,
+ Address ParamAddr, SourceLocation Loc) {
// Load the exception from where the landing pad saved it.
llvm::Value *Exn = CGF.getExceptionFromSlot();
CanQualType CatchType =
- CGF.CGM.getContext().getCanonicalType(CatchParam.getType());
+ CGF.CGM.getContext().getCanonicalType(CatchParam.getType());
llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType);
// If we're catching by reference, we can just cast the object
@@ -5007,31 +5000,31 @@ static void InitCatchParam(CodeGenFunction &CGF,
// Exn points to the struct _Unwind_Exception header, which
// we have to skip past in order to reach the exception data.
unsigned HeaderSize =
- CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException();
+ CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException();
AdjustedExn =
CGF.Builder.CreateConstGEP1_32(CGF.Int8Ty, Exn, HeaderSize);
- // However, if we're catching a pointer-to-record type that won't
- // work, because the personality function might have adjusted
- // the pointer. There's actually no way for us to fully satisfy
- // the language/ABI contract here: we can't use Exn because it
- // might have the wrong adjustment, but we can't use the by-value
- // pointer because it's off by a level of abstraction.
- //
- // The current solution is to dump the adjusted pointer into an
- // alloca, which breaks language semantics (because changing the
- // pointer doesn't change the exception) but at least works.
- // The better solution would be to filter out non-exact matches
- // and rethrow them, but this is tricky because the rethrow
- // really needs to be catchable by other sites at this landing
- // pad. The best solution is to fix the personality function.
+ // However, if we're catching a pointer-to-record type that won't
+ // work, because the personality function might have adjusted
+ // the pointer. There's actually no way for us to fully satisfy
+ // the language/ABI contract here: we can't use Exn because it
+ // might have the wrong adjustment, but we can't use the by-value
+ // pointer because it's off by a level of abstraction.
+ //
+ // The current solution is to dump the adjusted pointer into an
+ // alloca, which breaks language semantics (because changing the
+ // pointer doesn't change the exception) but at least works.
+ // The better solution would be to filter out non-exact matches
+ // and rethrow them, but this is tricky because the rethrow
+ // really needs to be catchable by other sites at this landing
+ // pad. The best solution is to fix the personality function.
} else {
// Pull the pointer for the reference type off.
llvm::Type *PtrTy = CGF.ConvertTypeForMem(CaughtType);
// Create the temporary and write the adjusted pointer into it.
Address ExnPtrTmp =
- CGF.CreateTempAlloca(PtrTy, CGF.getPointerAlign(), "exn.byref.tmp");
+ CGF.CreateTempAlloca(PtrTy, CGF.getPointerAlign(), "exn.byref.tmp");
llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
CGF.Builder.CreateStore(Casted, ExnPtrTmp);
@@ -5041,7 +5034,7 @@ static void InitCatchParam(CodeGenFunction &CGF,
}
llvm::Value *ExnCast =
- CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");
+ CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");
CGF.Builder.CreateStore(ExnCast, ParamAddr);
return;
}
@@ -5055,7 +5048,7 @@ static void InitCatchParam(CodeGenFunction &CGF,
// the pointer by value.
if (CatchType->hasPointerRepresentation()) {
llvm::Value *CastExn =
- CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");
+ CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");
switch (CatchType.getQualifiers().getObjCLifetime()) {
case Qualifiers::OCL_Strong:
@@ -5117,7 +5110,7 @@ static void InitCatchParam(CodeGenFunction &CGF,
// We have to call __cxa_get_exception_ptr to get the adjusted
// pointer before copying.
llvm::CallInst *rawAdjustedExn =
- CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn);
+ CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn);
// Cast that to the appropriate type.
Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),
@@ -5125,20 +5118,19 @@ static void InitCatchParam(CodeGenFunction &CGF,
// The copy expression is defined in terms of an OpaqueValueExpr.
// Find it and map it to the adjusted expression.
- CodeGenFunction::OpaqueValueMapping
- opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr),
- CGF.MakeAddrLValue(adjustedExn, CatchParam.getType()));
+ CodeGenFunction::OpaqueValueMapping opaque(
+ CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr),
+ CGF.MakeAddrLValue(adjustedExn, CatchParam.getType()));
// Call the copy ctor in a terminate scope.
CGF.EHStack.pushTerminate();
// Perform the copy construction.
- CGF.EmitAggExpr(copyExpr,
- AggValueSlot::forAddr(ParamAddr, Qualifiers(),
- AggValueSlot::IsNotDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased,
- AggValueSlot::DoesNotOverlap));
+ CGF.EmitAggExpr(
+ copyExpr, AggValueSlot::forAddr(
+ ParamAddr, Qualifiers(), AggValueSlot::IsNotDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers,
+ AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap));
// Leave the terminate scope.
CGF.EHStack.popTerminate();
diff --git a/compiler-rt/test/asan/TestCases/invalid-pointer-pairs-vector-extract.cpp b/compiler-rt/test/asan/TestCases/invalid-pointer-pairs-vector-extract.cpp
index 8c93ffa71ab30..2eea39ba91e17 100644
--- a/compiler-rt/test/asan/TestCases/invalid-pointer-pairs-vector-extract.cpp
+++ b/compiler-rt/test/asan/TestCases/invalid-pointer-pairs-vector-extract.cpp
@@ -4,8 +4,6 @@
// RUN: %env_asan_opts=detect_invalid_pointer_pairs=2:halt_on_error=0 %run %t 2>&1 | FileCheck %s
// UNSUPPORTED: windows
-// UNSUPPORTED: target={{.*solaris.*}}
-
// XFAIL: *
#include <cstdint>
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/SymbolLookupSet.h b/llvm/include/llvm/ExecutionEngine/Orc/SymbolLookupSet.h
index a3adf21986aea..bad4cd6052b8d 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/SymbolLookupSet.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/SymbolLookupSet.h
@@ -225,33 +225,12 @@ class SymbolLookupSet {
});
}
- /// Merge entries that share a name, so that each name appears exactly once.
- /// If a SymbolLookupSet is not duplicate-free by construction, this method
- /// can be used to turn it into a proper set.
- ///
- /// Entries sharing a name need not agree on their flags. Where they differ
- /// the strongest requirement wins: if any entry required the symbol then the
- /// merged entry requires it too, so that a missing definition still fails the
- /// lookup.
- void mergeEntries() {
- if (Symbols.size() < 2)
- return;
+ /// Remove any duplicate elements. If a SymbolLookupSet is not duplicate-free
+ /// by construction, this method can be used to turn it into a proper set.
+ void removeDuplicates() {
sortByAddress();
-
- auto Out = Symbols.begin();
- for (auto In = Out + 1; In != Symbols.end(); ++In) {
- if (In->first == Out->first) {
- // Same name: keep the stronger requirement.
- if (In->second == SymbolLookupFlags::RequiredSymbol)
- Out->second = SymbolLookupFlags::RequiredSymbol;
- } else {
- // New name: compact it down next to the previous survivor.
- ++Out;
- if (Out != In)
- *Out = std::move(*In);
- }
- }
- Symbols.erase(std::next(Out), Symbols.end());
+ auto LastI = llvm::unique(Symbols);
+ Symbols.erase(LastI, Symbols.end());
}
#ifndef NDEBUG
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index d078117061677..d7c37a021169e 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -2173,8 +2173,8 @@ bool X86DAGToDAGISel::matchAdd(SDValue &N, X86ISelAddressMode &AM,
};
X86ISelAddressMode Backup = AM;
- if (!MatchOperand(N.getOperand(0)) &&
- !MatchOperand(Handle.getValue().getOperand(1)))
+ if (!matchAddressRecursively(N.getOperand(0), AM, Depth + 1) &&
+ !matchAddressRecursively(Handle.getValue().getOperand(1), AM, Depth + 1))
return false;
AM = Backup;
diff --git a/llvm/test/Transforms/SLPVectorizer/AMDGPU/elementwise-fma-operand1.ll b/llvm/test/Transforms/SLPVectorizer/AMDGPU/elementwise-fma-operand1.ll
index c4c97622ac726..3bcc9f03d0220 100644
--- a/llvm/test/Transforms/SLPVectorizer/AMDGPU/elementwise-fma-operand1.ll
+++ b/llvm/test/Transforms/SLPVectorizer/AMDGPU/elementwise-fma-operand1.ll
@@ -2,17 +2,12 @@
; RUN: opt -passes=slp-vectorizer -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -slp-threshold=14 < %s | FileCheck %s
; RUN: opt -passes=slp-vectorizer -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx942 -slp-threshold=14 < %s | FileCheck %s
; RUN: opt -passes=slp-vectorizer -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx950 -slp-threshold=14 < %s | FileCheck %s
-; RUN: opt -passes=slp-vectorizer -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -slp-threshold=12 < %s | FileCheck %s --check-prefix=THR12
-; RUN: opt -passes=slp-vectorizer -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx942 -slp-threshold=12 < %s | FileCheck %s --check-prefix=THR12
-; RUN: opt -passes=slp-vectorizer -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx950 -slp-threshold=12 < %s | FileCheck %s --check-prefix=THR12
-; Elementwise d = c + a * b, where the fmul is operand 1 of the fadd. These
-; targets halve the cost of a packed fmul, so SLP is tempted to vectorize and
-; break the scalar fma chain. The 14 runs sit at the cost boundary. The 12 runs
-; vectorize either way and guard against the fmuladd marking landing on the load
-; at operand 0 after the fma detection picked the fmul at operand 1, which
-; asserts. axpy4_mixed_reassoc carries reassoc on one lane only, so the whole
-; bundle has to be reassociative before the search gives up on operand 1.
+; Elementwise d = c + a * b, where the fmul is operand 1 of the fadd. The
+; threshold puts the decision right at the cost boundary, so how the fmul and
+; fadd are priced against a fused fma is what decides it. These targets halve
+; the cost of a packed fmul, which is what tempts SLP into vectorizing and
+; breaking the scalar fma chain.
define void @axpy4_contract(ptr noalias %d, ptr noalias %a, ptr noalias %b, ptr noalias %c) {
; CHECK-LABEL: define void @axpy4_contract(
@@ -26,17 +21,6 @@ define void @axpy4_contract(ptr noalias %d, ptr noalias %a, ptr noalias %b, ptr
; CHECK-NEXT: store <4 x float> [[TMP4]], ptr [[D]], align 4
; CHECK-NEXT: ret void
;
-; THR12-LABEL: define void @axpy4_contract(
-; THR12-SAME: ptr noalias [[D:%.*]], ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR0:[0-9]+]] {
-; THR12-NEXT: [[ENTRY:.*:]]
-; THR12-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[C]], align 4
-; THR12-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[A]], align 4
-; THR12-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr [[B]], align 4
-; THR12-NEXT: [[TMP3:%.*]] = fmul contract <4 x float> [[TMP1]], [[TMP2]]
-; THR12-NEXT: [[TMP4:%.*]] = fadd contract <4 x float> [[TMP0]], [[TMP3]]
-; THR12-NEXT: store <4 x float> [[TMP4]], ptr [[D]], align 4
-; THR12-NEXT: ret void
-;
entry:
%c0 = load float, ptr %c, align 4
%a0 = load float, ptr %a, align 4
@@ -89,17 +73,6 @@ define void @axpy4_reassoc(ptr noalias %d, ptr noalias %a, ptr noalias %b, ptr n
; CHECK-NEXT: store <4 x float> [[TMP4]], ptr [[D]], align 4
; CHECK-NEXT: ret void
;
-; THR12-LABEL: define void @axpy4_reassoc(
-; THR12-SAME: ptr noalias [[D:%.*]], ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR0]] {
-; THR12-NEXT: [[ENTRY:.*:]]
-; THR12-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[C]], align 4
-; THR12-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[A]], align 4
-; THR12-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr [[B]], align 4
-; THR12-NEXT: [[TMP3:%.*]] = fmul reassoc contract <4 x float> [[TMP1]], [[TMP2]]
-; THR12-NEXT: [[TMP4:%.*]] = fadd reassoc contract <4 x float> [[TMP0]], [[TMP3]]
-; THR12-NEXT: store <4 x float> [[TMP4]], ptr [[D]], align 4
-; THR12-NEXT: ret void
-;
entry:
%c0 = load float, ptr %c, align 4
%a0 = load float, ptr %a, align 4
@@ -139,66 +112,3 @@ entry:
store float %r3, ptr %dp3, align 4
ret void
}
-
-define void @axpy4_mixed_reassoc(ptr noalias %d, ptr noalias %a, ptr noalias %b, ptr noalias %c) {
-; CHECK-LABEL: define void @axpy4_mixed_reassoc(
-; CHECK-SAME: ptr noalias [[D:%.*]], ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[C]], align 4
-; CHECK-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[A]], align 4
-; CHECK-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr [[B]], align 4
-; CHECK-NEXT: [[TMP3:%.*]] = fmul contract <4 x float> [[TMP1]], [[TMP2]]
-; CHECK-NEXT: [[TMP4:%.*]] = fadd contract <4 x float> [[TMP0]], [[TMP3]]
-; CHECK-NEXT: store <4 x float> [[TMP4]], ptr [[D]], align 4
-; CHECK-NEXT: ret void
-;
-; THR12-LABEL: define void @axpy4_mixed_reassoc(
-; THR12-SAME: ptr noalias [[D:%.*]], ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR0]] {
-; THR12-NEXT: [[ENTRY:.*:]]
-; THR12-NEXT: [[TMP0:%.*]] = load <4 x float>, ptr [[C]], align 4
-; THR12-NEXT: [[TMP1:%.*]] = load <4 x float>, ptr [[A]], align 4
-; THR12-NEXT: [[TMP2:%.*]] = load <4 x float>, ptr [[B]], align 4
-; THR12-NEXT: [[TMP3:%.*]] = fmul contract <4 x float> [[TMP1]], [[TMP2]]
-; THR12-NEXT: [[TMP4:%.*]] = fadd contract <4 x float> [[TMP0]], [[TMP3]]
-; THR12-NEXT: store <4 x float> [[TMP4]], ptr [[D]], align 4
-; THR12-NEXT: ret void
-;
-entry:
- %c0 = load float, ptr %c, align 4
- %a0 = load float, ptr %a, align 4
- %b0 = load float, ptr %b, align 4
- %m0 = fmul contract float %a0, %b0
- %r0 = fadd contract reassoc float %c0, %m0
- store float %r0, ptr %d, align 4
- %cp1 = getelementptr inbounds float, ptr %c, i64 1
- %c1 = load float, ptr %cp1, align 4
- %ap1 = getelementptr inbounds float, ptr %a, i64 1
- %a1 = load float, ptr %ap1, align 4
- %bp1 = getelementptr inbounds float, ptr %b, i64 1
- %b1 = load float, ptr %bp1, align 4
- %m1 = fmul contract float %a1, %b1
- %r1 = fadd contract float %c1, %m1
- %dp1 = getelementptr inbounds float, ptr %d, i64 1
- store float %r1, ptr %dp1, align 4
- %cp2 = getelementptr inbounds float, ptr %c, i64 2
- %c2 = load float, ptr %cp2, align 4
- %ap2 = getelementptr inbounds float, ptr %a, i64 2
- %a2 = load float, ptr %ap2, align 4
- %bp2 = getelementptr inbounds float, ptr %b, i64 2
- %b2 = load float, ptr %bp2, align 4
- %m2 = fmul contract float %a2, %b2
- %r2 = fadd contract float %c2, %m2
- %dp2 = getelementptr inbounds float, ptr %d, i64 2
- store float %r2, ptr %dp2, align 4
- %cp3 = getelementptr inbounds float, ptr %c, i64 3
- %c3 = load float, ptr %cp3, align 4
- %ap3 = getelementptr inbounds float, ptr %a, i64 3
- %a3 = load float, ptr %ap3, align 4
- %bp3 = getelementptr inbounds float, ptr %b, i64 3
- %b3 = load float, ptr %bp3, align 4
- %m3 = fmul contract float %a3, %b3
- %r3 = fadd contract float %c3, %m3
- %dp3 = getelementptr inbounds float, ptr %d, i64 3
- store float %r3, ptr %dp3, align 4
- ret void
-}
diff --git a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
index ac648b3f420bf..8af05a8b32e8f 100644
--- a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
@@ -49,7 +49,6 @@ add_llvm_unittest(OrcJITTests
SimpleExecutorMemoryManagerTest.cpp
SimplePackedSerializationTest.cpp
SPSProxySpecTest.cpp
- SymbolLookupSetTest.cpp
SymbolStringPoolTest.cpp
TaskDispatchTest.cpp
ThreadSafeModuleTest.cpp
diff --git a/llvm/unittests/ExecutionEngine/Orc/SymbolLookupSetTest.cpp b/llvm/unittests/ExecutionEngine/Orc/SymbolLookupSetTest.cpp
deleted file mode 100644
index 95c3884e0b8e8..0000000000000
--- a/llvm/unittests/ExecutionEngine/Orc/SymbolLookupSetTest.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-//===- SymbolLookupSetTest.cpp - Test SymbolLookupSet --------------------===//
-//
-// 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 "llvm/ExecutionEngine/Orc/SymbolLookupSet.h"
-
-#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
-
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "gtest/gtest.h"
-
-using namespace llvm;
-using namespace llvm::orc;
-
-namespace {
-
-class SymbolLookupSetTest : public testing::Test {
-protected:
- static constexpr SymbolLookupFlags Required =
- SymbolLookupFlags::RequiredSymbol;
- static constexpr SymbolLookupFlags Weak =
- SymbolLookupFlags::WeaklyReferencedSymbol;
-
- std::shared_ptr<SymbolStringPool> SSP = std::make_shared<SymbolStringPool>();
-
- SymbolStringPtr intern(StringRef S) { return SSP->intern(S); }
-
- /// Collect a lookup set into a name-sorted vector of (name, flags).
- ///
- /// A vector rather than a map so that a name surviving more than once is
- /// visible, and name-sorted because mergeEntries sorts by pointer value,
- /// leaving an order that depends on allocation and must not be asserted on.
- using Entries = std::vector<std::pair<std::string, SymbolLookupFlags>>;
-
- static Entries contents(const SymbolLookupSet &LS) {
- Entries Result;
- for (const auto &[Name, Flags] : LS)
- Result.emplace_back(std::string(*Name), Flags);
- llvm::sort(Result);
- return Result;
- }
-};
-
-} // namespace
-
-// A set that is already duplicate-free is left alone, flags included.
-TEST_F(SymbolLookupSetTest, MergeEntriesNoDuplicates) {
- SymbolLookupSet LS;
- LS.add(intern("foo"), Required);
- LS.add(intern("bar"), Weak);
-
- LS.mergeEntries();
-
- EXPECT_EQ(contents(LS), (Entries{{"bar", Weak}, {"foo", Required}}));
-}
-
-// Duplicates that agree on flags collapse to a single entry.
-TEST_F(SymbolLookupSetTest, MergeEntriesSameFlags) {
- SymbolLookupSet LS;
- LS.add(intern("foo"), Required);
- LS.add(intern("foo"), Required);
- LS.add(intern("bar"), Weak);
- LS.add(intern("bar"), Weak);
-
- LS.mergeEntries();
-
- EXPECT_EQ(contents(LS), (Entries{{"bar", Weak}, {"foo", Required}}));
-}
-
-// A name requested both ways merges to RequiredSymbol: if any requester needs
-// the symbol then a missing definition must fail the lookup.
-//
-// Both insertion orders are checked because mergeEntries sorts by pointer
-// value, so which of the two entries is seen first is not under our control.
-TEST_F(SymbolLookupSetTest, MergeEntriesRequiredWinsWeakFirst) {
- SymbolLookupSet LS;
- LS.add(intern("foo"), Weak);
- LS.add(intern("foo"), Required);
-
- LS.mergeEntries();
-
- EXPECT_EQ(contents(LS), (Entries{{"foo", Required}}));
-}
-
-TEST_F(SymbolLookupSetTest, MergeEntriesRequiredWinsRequiredFirst) {
- SymbolLookupSet LS;
- LS.add(intern("foo"), Required);
- LS.add(intern("foo"), Weak);
-
- LS.mergeEntries();
-
- EXPECT_EQ(contents(LS), (Entries{{"foo", Required}}));
-}
-
-// Merging must not invent a requirement: all-weak duplicates stay weak.
-TEST_F(SymbolLookupSetTest, MergeEntriesAllWeakStaysWeak) {
- SymbolLookupSet LS;
- LS.add(intern("foo"), Weak);
- LS.add(intern("foo"), Weak);
- LS.add(intern("foo"), Weak);
-
- LS.mergeEntries();
-
- EXPECT_EQ(contents(LS), (Entries{{"foo", Weak}}));
-}
-
-// Several distinct names, each duplicated a different number of times and with
-// mixed flags, all merge in one pass.
-TEST_F(SymbolLookupSetTest, MergeEntriesMultipleRuns) {
- SymbolLookupSet LS;
- LS.add(intern("foo"), Weak);
- LS.add(intern("bar"), Required);
- LS.add(intern("foo"), Weak);
- LS.add(intern("baz"), Weak);
- LS.add(intern("bar"), Weak);
- LS.add(intern("foo"), Required);
- LS.add(intern("qux"), Required);
-
- LS.mergeEntries();
-
- EXPECT_EQ(contents(LS), (Entries{{"bar", Required},
- {"baz", Weak},
- {"foo", Required},
- {"qux", Required}}));
-}
diff --git a/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn
index 5659ddfea45e0..dfbf74b3cd1a9 100644
--- a/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn
@@ -48,7 +48,6 @@ unittest("OrcJITTests") {
"SharedMemoryMapperTest.cpp",
"SimpleExecutorMemoryManagerTest.cpp",
"SimplePackedSerializationTest.cpp",
- "SymbolLookupSetTest.cpp",
"SymbolStringPoolTest.cpp",
"TaskDispatchTest.cpp",
"ThreadSafeModuleTest.cpp",
diff --git a/orc-rt/include/CMakeLists.txt b/orc-rt/include/CMakeLists.txt
index 40c16d681e783..247d82ba709e6 100644
--- a/orc-rt/include/CMakeLists.txt
+++ b/orc-rt/include/CMakeLists.txt
@@ -32,7 +32,6 @@ set(ORC_RT_HEADERS
orc-rt/SimplePackedSerialization.h
orc-rt/SimpleSymbolTable.h
orc-rt/StandaloneMachOUnwindInfoRegistrar.h
- orc-rt/StringPool.h
orc-rt/TaskGroup.h
orc-rt/ThreadPoolRunner.h
orc-rt/WrapperFunction.h
diff --git a/orc-rt/include/orc-rt/StringPool.h b/orc-rt/include/orc-rt/StringPool.h
deleted file mode 100644
index 85014da2b2e54..0000000000000
--- a/orc-rt/include/orc-rt/StringPool.h
+++ /dev/null
@@ -1,249 +0,0 @@
-//===------------- StringPool.h - Interning string pool ---------*- 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
-//
-//===----------------------------------------------------------------------===//
-//
-// A thread-safe, ref-counted pool of uniqued strings.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ORC_RT_STRINGPOOL_H
-#define ORC_RT_STRINGPOOL_H
-
-#include <atomic>
-#include <cassert>
-#include <cstddef>
-#include <mutex>
-#include <string>
-#include <string_view>
-#include <unordered_map>
-#include <utility>
-
-namespace orc_rt {
-
-class PooledStringPtr;
-class NonOwningPooledStringPtr;
-
-/// Interns strings (e.g. symbol names, paths) behind ref-counted handles. An
-/// entry is kept alive as long as at least one PooledStringPtr refers to it;
-/// clearDeadEntries() reclaims entries with no owners left.
-///
-/// intern() and clearDeadEntries() may be called concurrently from any
-/// number of threads. Copying, moving, and destroying a PooledStringPtr
-/// requires no lock -- only the atomic refcount in that ptr's own entry is
-/// touched.
-class StringPool {
-private:
- using RefCount = std::atomic<size_t>;
- using PoolMap = std::unordered_map<std::string, RefCount>;
-
-public:
- using PoolEntry = PoolMap::value_type;
-
- StringPool() = default;
- StringPool(const StringPool &) = delete;
- StringPool &operator=(const StringPool &) = delete;
- ~StringPool();
-
- /// Returns the PooledStringPtr for S, interning a copy on first reference.
- PooledStringPtr intern(std::string_view S);
-
- /// Erase entries with no remaining PooledStringPtr owners.
- void clearDeadEntries();
-
- /// Returns true if this pool has no entries.
- bool empty() const;
-
-private:
- mutable std::mutex M;
- PoolMap Pool;
-};
-
-/// Common base for PooledStringPtr and NonOwningPooledStringPtr: bool
-/// conversion, dereference, and comparison.
-///
-/// Comparisons and hashing are pointer-identity, scoped to whichever
-/// StringPool produced the handle -- handles from different pools are never
-/// equal, even for identical text.
-class PooledStringPtrBase {
- friend class StringPoolEntryUnsafe;
-
-public:
- PooledStringPtrBase() = default;
- PooledStringPtrBase(std::nullptr_t) noexcept {}
-
- explicit operator bool() const noexcept { return E != nullptr; }
-
- const std::string &operator*() const noexcept { return E->first; }
-
- friend bool operator==(PooledStringPtrBase LHS,
- PooledStringPtrBase RHS) noexcept {
- return LHS.E == RHS.E;
- }
- friend bool operator!=(PooledStringPtrBase LHS,
- PooledStringPtrBase RHS) noexcept {
- return !(LHS == RHS);
- }
- // Pointer-order only; not stable across runs (ASLR). Fine as a map/set key
- // ordering, not for anything user-visible.
- friend bool operator<(PooledStringPtrBase LHS,
- PooledStringPtrBase RHS) noexcept {
- return LHS.E < RHS.E;
- }
-
-protected:
- using PoolEntry = StringPool::PoolEntry;
-
- explicit PooledStringPtrBase(PoolEntry *E) noexcept : E(E) {}
- PoolEntry *E = nullptr;
-};
-
-/// An owning, ref-counted handle to a string interned in some StringPool.
-class PooledStringPtr : public PooledStringPtrBase {
- friend class StringPool;
-
-public:
- PooledStringPtr() = default;
- PooledStringPtr(std::nullptr_t) noexcept {}
-
- /// Constructs an owning handle from a non-owning one, incrementing the
- /// refcount. Other must be backed by an entry that some PooledStringPtr is
- /// already keeping alive -- constructing from a NonOwningPooledStringPtr
- /// whose entry has already been reclaimed by clearDeadEntries() is
- /// undefined behavior.
- explicit PooledStringPtr(NonOwningPooledStringPtr Other) noexcept;
-
- PooledStringPtr(const PooledStringPtr &Other) noexcept
- : PooledStringPtrBase(Other.E) {
- incRef();
- }
-
- PooledStringPtr &operator=(const PooledStringPtr &Other) noexcept {
- if (this != &Other) {
- decRef();
- E = Other.E;
- incRef();
- }
- return *this;
- }
-
- PooledStringPtr(PooledStringPtr &&Other) noexcept { std::swap(E, Other.E); }
-
- PooledStringPtr &operator=(PooledStringPtr &&Other) noexcept {
- decRef();
- E = nullptr;
- std::swap(E, Other.E);
- return *this;
- }
-
- ~PooledStringPtr() { decRef(); }
-
-private:
- explicit PooledStringPtr(PoolEntry *E) noexcept : PooledStringPtrBase(E) {
- incRef();
- }
-
- void incRef() noexcept {
- if (E)
- ++E->second;
- }
-
- void decRef() noexcept {
- if (E) {
- assert(E->second.load() != 0 && "double-release of PooledStringPtr");
- --E->second;
- }
- }
-};
-
-/// A non-owning handle to a string interned in some StringPool.
-///
-/// Comparable and hashable interchangeably with PooledStringPtr (both wrap the
-/// same underlying entry pointer), but copying a NonOwningPooledStringPtr never
-/// touches the refcount, so it's cheaper to pass around than a PooledStringPtr.
-/// It is silently invalidated if the entry's refcount drops to zero and is
-/// reclaimed by clearDeadEntries(), so only use it where a corresponding
-/// PooledStringPtr is known to be keeping the entry alive -- e.g. as a lookup
-/// key into a table whose values (or a side table) hold the owning
-/// PooledStringPtr for that same entry.
-class NonOwningPooledStringPtr : public PooledStringPtrBase {
-public:
- NonOwningPooledStringPtr() = default;
- NonOwningPooledStringPtr(std::nullptr_t) noexcept {}
- explicit NonOwningPooledStringPtr(const PooledStringPtr &Other) noexcept
- : PooledStringPtrBase(Other) {}
-};
-
-/// Provides unsafe (refcount-bypassing) access to the pool-entry pointer
-/// underlying a PooledStringPtrBase. Used to implement std::hash and C API
-/// operations. Not intended for general use.
-class StringPoolEntryUnsafe {
-public:
- using PoolEntry = StringPool::PoolEntry;
-
- /// Extracts the pool-entry pointer from S without affecting its refcount.
- static StringPoolEntryUnsafe from(const PooledStringPtrBase &S) {
- return StringPoolEntryUnsafe(S.E);
- }
-
- const void *rawPtr() const { return E; }
-
-private:
- StringPoolEntryUnsafe(PoolEntry *E) : E(E) {}
- PoolEntry *E = nullptr;
-};
-
-inline PooledStringPtr::PooledStringPtr(NonOwningPooledStringPtr Other) noexcept
- : PooledStringPtrBase(Other) {
- incRef();
-}
-
-inline StringPool::~StringPool() {
-#ifndef NDEBUG
- clearDeadEntries();
- assert(Pool.empty() && "Dangling PooledStringPtr at StringPool destruction");
-#endif
-}
-
-inline PooledStringPtr StringPool::intern(std::string_view S) {
- std::scoped_lock<std::mutex> Lock(M);
- auto [I, Added] = Pool.try_emplace(std::string(S), 0);
- return PooledStringPtr(&*I);
-}
-
-inline void StringPool::clearDeadEntries() {
- std::scoped_lock<std::mutex> Lock(M);
- for (auto I = Pool.begin(), E = Pool.end(); I != E;)
- if (I->second.load() == 0)
- I = Pool.erase(I);
- else
- ++I;
-}
-
-inline bool StringPool::empty() const {
- std::scoped_lock<std::mutex> Lock(M);
- return Pool.empty();
-}
-
-} // namespace orc_rt
-
-namespace std {
-template <> struct hash<orc_rt::PooledStringPtr> {
- size_t operator()(const orc_rt::PooledStringPtr &S) const noexcept {
- return hash<const void *>()(
- orc_rt::StringPoolEntryUnsafe::from(S).rawPtr());
- }
-};
-
-template <> struct hash<orc_rt::NonOwningPooledStringPtr> {
- size_t operator()(const orc_rt::NonOwningPooledStringPtr &S) const noexcept {
- return hash<const void *>()(
- orc_rt::StringPoolEntryUnsafe::from(S).rawPtr());
- }
-};
-} // namespace std
-
-#endif // ORC_RT_STRINGPOOL_H
diff --git a/orc-rt/test/unit/CMakeLists.txt b/orc-rt/test/unit/CMakeLists.txt
index 1916000506e31..7219c9897de1e 100644
--- a/orc-rt/test/unit/CMakeLists.txt
+++ b/orc-rt/test/unit/CMakeLists.txt
@@ -50,7 +50,6 @@ add_orc_rt_unittest(CoreTests
SimpleSymbolTableTest.cpp
StandaloneMachOUnwindInfoRegistrarTest.cpp
StringExtrasTest.cpp
- StringPoolTest.cpp
TaskGroupTest.cpp
ThreadPoolRunnerTest.cpp
WrapperFunctionBufferTest.cpp
diff --git a/orc-rt/test/unit/StringPoolTest.cpp b/orc-rt/test/unit/StringPoolTest.cpp
deleted file mode 100644
index 85b866d12a275..0000000000000
--- a/orc-rt/test/unit/StringPoolTest.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-//===- StringPoolTest.cpp -------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// Tests for orc-rt's StringPool.h APIs.
-//
-//===----------------------------------------------------------------------===//
-
-#include "orc-rt/StringPool.h"
-#include "gtest/gtest.h"
-
-#include <unordered_set>
-
-using namespace orc_rt;
-
-TEST(StringPoolTest, EmptyByDefault) {
- StringPool SP;
- EXPECT_TRUE(SP.empty());
-}
-
-TEST(StringPoolTest, InternReturnsEqualContent) {
- StringPool SP;
- auto Foo = SP.intern("foo");
- EXPECT_TRUE(Foo);
- EXPECT_EQ(*Foo, "foo");
- EXPECT_FALSE(SP.empty());
-}
-
-TEST(StringPoolTest, RepeatedInternIsIdentical) {
- StringPool SP;
- auto Foo1 = SP.intern("foo");
- auto Foo2 = SP.intern("foo");
- EXPECT_EQ(Foo1, Foo2);
-}
-
-TEST(StringPoolTest, DifferentContentIsDistinct) {
- StringPool SP;
- auto Foo = SP.intern("foo");
- auto Bar = SP.intern("bar");
- EXPECT_NE(Foo, Bar);
-}
-
-TEST(StringPoolTest, DifferentPoolsAreDistinct) {
- StringPool SP1, SP2;
- auto Foo1 = SP1.intern("foo");
- auto Foo2 = SP2.intern("foo");
- EXPECT_EQ(*Foo1, *Foo2);
- EXPECT_NE(Foo1, Foo2);
-}
-
-TEST(StringPoolTest, DefaultConstructedIsNull) {
- PooledStringPtr Null;
- EXPECT_FALSE(Null);
- EXPECT_EQ(Null, PooledStringPtr(nullptr));
-}
-
-TEST(StringPoolTest, CopyKeepsEntryAlive) {
- StringPool SP;
- PooledStringPtr Copy;
- {
- auto Foo = SP.intern("foo");
- Copy = Foo;
- }
- // Foo has been destroyed. If copy-assignment above failed to incRef, the
- // entry's refcount would already be zero and clearDeadEntries() would
- // reclaim it.
- SP.clearDeadEntries();
- ASSERT_FALSE(SP.empty()) << "Copy should have kept the entry alive";
- EXPECT_EQ(*Copy, "foo");
-}
-
-TEST(StringPoolTest, ClearDeadEntriesReclaimsUnreferenced) {
- StringPool SP;
- {
- auto Foo = SP.intern("foo");
- }
- EXPECT_FALSE(SP.empty());
- SP.clearDeadEntries();
- EXPECT_TRUE(SP.empty());
-}
-
-TEST(StringPoolTest, ClearDeadEntriesKeepsReferenced) {
- StringPool SP;
- auto Foo = SP.intern("foo");
- {
- auto Bar = SP.intern("bar");
- }
- SP.clearDeadEntries();
- ASSERT_FALSE(SP.empty());
- EXPECT_EQ(*Foo, "foo");
-}
-
-TEST(StringPoolTest, MoveLeavesSourceNull) {
- StringPool SP;
- auto Foo = SP.intern("foo");
- auto Moved = std::move(Foo);
- EXPECT_FALSE(Foo);
- EXPECT_TRUE(Moved);
- EXPECT_EQ(*Moved, "foo");
-}
-
-TEST(StringPoolTest, NonOwningPtrComparesEqualToOwning) {
- StringPool SP;
- auto Foo = SP.intern("foo");
- NonOwningPooledStringPtr NonOwningFoo(Foo);
- EXPECT_EQ(Foo, NonOwningFoo);
- EXPECT_EQ(*NonOwningFoo, "foo");
-}
-
-TEST(StringPoolTest, NonOwningPtrDoesNotKeepEntryAlive) {
- StringPool SP;
- NonOwningPooledStringPtr NonOwningFoo;
- {
- auto Foo = SP.intern("foo");
- NonOwningFoo = NonOwningPooledStringPtr(Foo);
- }
- // Foo has been destroyed and was the only owner, so the entry should be
- // reclaimed even though NonOwningFoo still points at it.
- SP.clearDeadEntries();
- EXPECT_TRUE(SP.empty());
-}
-
-TEST(StringPoolTest, ConstructOwningFromNonOwningIncrementsRefcount) {
- StringPool SP;
- NonOwningPooledStringPtr NonOwningFoo;
- {
- auto Foo = SP.intern("foo");
- NonOwningFoo = NonOwningPooledStringPtr(Foo);
- }
- // The entry's refcount is now zero, but it has not yet been reclaimed by
- // clearDeadEntries(), so re-deriving an owning ptr from NonOwningFoo here
- // is well-defined and should keep the entry alive.
- PooledStringPtr Reowned(NonOwningFoo);
- SP.clearDeadEntries();
- ASSERT_FALSE(SP.empty());
- EXPECT_EQ(*Reowned, "foo");
-}
-
-TEST(StringPoolTest, UsableAsUnorderedSetKey) {
- StringPool SP;
- auto Foo1 = SP.intern("foo");
- auto Foo2 = SP.intern("foo");
- auto Bar = SP.intern("bar");
-
- std::unordered_set<PooledStringPtr> S;
- S.insert(Foo1);
- S.insert(Foo2);
- S.insert(Bar);
-
- EXPECT_EQ(S.size(), 2U);
- EXPECT_TRUE(S.count(Foo1));
- EXPECT_TRUE(S.count(Bar));
-}
-
-TEST(StringPoolTest, OwningAndNonOwningHashInterchangeably) {
- StringPool SP;
- auto Foo = SP.intern("foo");
- NonOwningPooledStringPtr NonOwningFoo(Foo);
-
- EXPECT_EQ(std::hash<PooledStringPtr>()(Foo),
- std::hash<NonOwningPooledStringPtr>()(NonOwningFoo));
-}
More information about the llvm-commits
mailing list