aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGExprCXX.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-07-26 19:03:47 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-07-26 19:04:23 +0000
commit7fa27ce4a07f19b07799a767fc29416f3b625afb (patch)
tree27825c83636c4de341eb09a74f49f5d38a15d165 /clang/lib/CodeGen/CGExprCXX.cpp
parente3b557809604d036af6e00c60f012c2025b59a5e (diff)
Diffstat (limited to 'clang/lib/CodeGen/CGExprCXX.cpp')
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp106
1 files changed, 63 insertions, 43 deletions
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index b889a4e05ee1..4d3f3e9603d9 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -33,10 +33,12 @@ struct MemberCallInfo {
}
static MemberCallInfo
-commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD,
+commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, GlobalDecl GD,
llvm::Value *This, llvm::Value *ImplicitParam,
QualType ImplicitParamTy, const CallExpr *CE,
CallArgList &Args, CallArgList *RtlArgs) {
+ auto *MD = cast<CXXMethodDecl>(GD.getDecl());
+
assert(CE == nullptr || isa<CXXMemberCallExpr>(CE) ||
isa<CXXOperatorCallExpr>(CE));
assert(MD->isInstance() &&
@@ -44,7 +46,7 @@ commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD,
// Push the this ptr.
const CXXRecordDecl *RD =
- CGF.CGM.getCXXABI().getThisArgumentTypeForMethod(MD);
+ CGF.CGM.getCXXABI().getThisArgumentTypeForMethod(GD);
Args.add(RValue::get(This), CGF.getTypes().DeriveThisType(RD, MD));
// If there is an implicit parameter (e.g. VTT), emit it.
@@ -110,7 +112,7 @@ RValue CodeGenFunction::EmitCXXDestructorCall(
}
CallArgList Args;
- commonEmitCXXMemberOrOperatorCall(*this, DtorDecl, This, ImplicitParam,
+ commonEmitCXXMemberOrOperatorCall(*this, Dtor, This, ImplicitParam,
ImplicitParamTy, CE, Args, nullptr);
return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(Dtor), Callee,
ReturnValueSlot(), Args, nullptr, CE && CE == MustTailCall,
@@ -285,7 +287,8 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
assert(ReturnValue.isNull() && "Constructor shouldn't have return value");
CallArgList Args;
commonEmitCXXMemberOrOperatorCall(
- *this, Ctor, This.getPointer(*this), /*ImplicitParam=*/nullptr,
+ *this, {Ctor, Ctor_Complete}, This.getPointer(*this),
+ /*ImplicitParam=*/nullptr,
/*ImplicitParamTy=*/QualType(), CE, Args, nullptr);
EmitCXXConstructorCall(Ctor, Ctor_Complete, /*ForVirtualBase=*/false,
@@ -443,9 +446,9 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
// Emit the 'this' pointer.
Address This = Address::invalid();
if (BO->getOpcode() == BO_PtrMemI)
- This = EmitPointerWithAlignment(BaseExpr);
+ This = EmitPointerWithAlignment(BaseExpr, nullptr, nullptr, KnownNonNull);
else
- This = EmitLValue(BaseExpr).getAddress(*this);
+ This = EmitLValue(BaseExpr, KnownNonNull).getAddress(*this);
EmitTypeCheck(TCK_MemberCall, E->getExprLoc(), This.getPointer(),
QualType(MPT->getClass(), 0));
@@ -499,7 +502,7 @@ static void EmitNullBaseClassInitialization(CodeGenFunction &CGF,
if (Base->isEmpty())
return;
- DestPtr = CGF.Builder.CreateElementBitCast(DestPtr, CGF.Int8Ty);
+ DestPtr = DestPtr.withElementType(CGF.Int8Ty);
const ASTRecordLayout &Layout = CGF.getContext().getASTRecordLayout(Base);
CharUnits NVSize = Layout.getNonVirtualSize();
@@ -552,8 +555,7 @@ static void EmitNullBaseClassInitialization(CodeGenFunction &CGF,
std::max(Layout.getNonVirtualAlignment(), DestPtr.getAlignment());
NullVariable->setAlignment(Align.getAsAlign());
- Address SrcPtr =
- Address(CGF.EmitCastToVoidPtr(NullVariable), CGF.Int8Ty, Align);
+ Address SrcPtr(NullVariable, CGF.Int8Ty, Align);
// Get and call the appropriate llvm.memcpy overload.
for (std::pair<CharUnits, CharUnits> Store : Stores) {
@@ -765,7 +767,7 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
// wider than that, check whether it's already too big, and if so,
// overflow.
else if (numElementsWidth > sizeWidth &&
- numElementsWidth - sizeWidth > count.countLeadingZeros())
+ numElementsWidth - sizeWidth > count.countl_zero())
hasAnyOverflow = true;
// Okay, compute a count at the right width.
@@ -826,8 +828,8 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
// going to have to do a comparison for (2), and this happens to
// take care of (1), too.
if (numElementsWidth > sizeWidth) {
- llvm::APInt threshold(numElementsWidth, 1);
- threshold <<= sizeWidth;
+ llvm::APInt threshold =
+ llvm::APInt::getOneBitSet(numElementsWidth, sizeWidth);
llvm::Value *thresholdV
= llvm::ConstantInt::get(numElementsType, threshold);
@@ -1074,7 +1076,7 @@ void CodeGenFunction::EmitNewArrayInitializer(
if (const ConstantArrayType *CAT = dyn_cast_or_null<ConstantArrayType>(
AllocType->getAsArrayTypeUnsafe())) {
ElementTy = ConvertTypeForMem(AllocType);
- CurPtr = Builder.CreateElementBitCast(CurPtr, ElementTy);
+ CurPtr = CurPtr.withElementType(ElementTy);
InitListElements *= getContext().getConstantArrayElementCount(CAT);
}
@@ -1131,7 +1133,7 @@ void CodeGenFunction::EmitNewArrayInitializer(
}
// Switch back to initializing one base element at a time.
- CurPtr = Builder.CreateElementBitCast(CurPtr, BeginPtr.getElementType());
+ CurPtr = CurPtr.withElementType(BeginPtr.getElementType());
}
// If all elements have already been initialized, skip any further
@@ -1654,7 +1656,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
CharUnits allocationAlign = allocAlign;
if (!E->passAlignment() &&
allocator->isReplaceableGlobalAllocationFunction()) {
- unsigned AllocatorAlign = llvm::PowerOf2Floor(std::min<uint64_t>(
+ unsigned AllocatorAlign = llvm::bit_floor(std::min<uint64_t>(
Target.getNewAlign(), getContext().getTypeSize(allocType)));
allocationAlign = std::max(
allocationAlign, getContext().toCharUnitsFromBits(AllocatorAlign));
@@ -1713,7 +1715,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
}
llvm::Type *elementTy = ConvertTypeForMem(allocType);
- Address result = Builder.CreateElementBitCast(allocation, elementTy);
+ Address result = allocation.withElementType(elementTy);
// Passing pointer through launder.invariant.group to avoid propagation of
// vptrs information which may be included in previous type.
@@ -2071,6 +2073,7 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull);
EmitBlock(DeleteNotNull);
+ Ptr.setKnownNonNull();
QualType DeleteTy = E->getDestroyedType();
@@ -2103,7 +2106,8 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
Ptr = Address(Builder.CreateInBoundsGEP(Ptr.getElementType(),
Ptr.getPointer(), GEP, "del.first"),
- ConvertTypeForMem(DeleteTy), Ptr.getAlignment());
+ ConvertTypeForMem(DeleteTy), Ptr.getAlignment(),
+ Ptr.isKnownNonNull());
}
assert(ConvertTypeForMem(DeleteTy) == Ptr.getElementType());
@@ -2190,13 +2194,12 @@ static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const Expr *E,
}
llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
- llvm::Type *StdTypeInfoPtrTy =
- ConvertType(E->getType())->getPointerTo();
+ llvm::Type *PtrTy = llvm::PointerType::getUnqual(getLLVMContext());
if (E->isTypeOperand()) {
llvm::Constant *TypeInfo =
CGM.GetAddrOfRTTIDescriptor(E->getTypeOperand(getContext()));
- return Builder.CreateBitCast(TypeInfo, StdTypeInfoPtrTy);
+ return TypeInfo;
}
// C++ [expr.typeid]p2:
@@ -2206,12 +2209,10 @@ llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
// type) to which the glvalue refers.
// If the operand is already most derived object, no need to look up vtable.
if (E->isPotentiallyEvaluated() && !E->isMostDerived(getContext()))
- return EmitTypeidFromVTable(*this, E->getExprOperand(),
- StdTypeInfoPtrTy);
+ return EmitTypeidFromVTable(*this, E->getExprOperand(), PtrTy);
QualType OperandTy = E->getExprOperand()->getType();
- return Builder.CreateBitCast(CGM.GetAddrOfRTTIDescriptor(OperandTy),
- StdTypeInfoPtrTy);
+ return CGM.GetAddrOfRTTIDescriptor(OperandTy);
}
static llvm::Value *EmitDynamicCastToNull(CodeGenFunction &CGF,
@@ -2225,8 +2226,8 @@ static llvm::Value *EmitDynamicCastToNull(CodeGenFunction &CGF,
if (!CGF.CGM.getCXXABI().EmitBadCastCall(CGF))
return nullptr;
- CGF.EmitBlock(CGF.createBasicBlock("dynamic_cast.end"));
- return llvm::UndefValue::get(DestLTy);
+ CGF.Builder.ClearInsertionPoint();
+ return llvm::PoisonValue::get(DestLTy);
}
llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr,
@@ -2239,17 +2240,16 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr,
// C++ [expr.dynamic.cast]p7:
// If T is "pointer to cv void," then the result is a pointer to the most
// derived object pointed to by v.
- const PointerType *DestPTy = DestTy->getAs<PointerType>();
-
- bool isDynamicCastToVoid;
+ bool IsDynamicCastToVoid = DestTy->isVoidPointerType();
QualType SrcRecordTy;
QualType DestRecordTy;
- if (DestPTy) {
- isDynamicCastToVoid = DestPTy->getPointeeType()->isVoidType();
+ if (IsDynamicCastToVoid) {
+ SrcRecordTy = SrcTy->getPointeeType();
+ // No DestRecordTy.
+ } else if (const PointerType *DestPTy = DestTy->getAs<PointerType>()) {
SrcRecordTy = SrcTy->castAs<PointerType>()->getPointeeType();
DestRecordTy = DestPTy->getPointeeType();
} else {
- isDynamicCastToVoid = false;
SrcRecordTy = SrcTy;
DestRecordTy = DestTy->castAs<ReferenceType>()->getPointeeType();
}
@@ -2262,18 +2262,30 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr,
EmitTypeCheck(TCK_DynamicOperation, DCE->getExprLoc(), ThisAddr.getPointer(),
SrcRecordTy);
- if (DCE->isAlwaysNull())
- if (llvm::Value *T = EmitDynamicCastToNull(*this, DestTy))
+ if (DCE->isAlwaysNull()) {
+ if (llvm::Value *T = EmitDynamicCastToNull(*this, DestTy)) {
+ // Expression emission is expected to retain a valid insertion point.
+ if (!Builder.GetInsertBlock())
+ EmitBlock(createBasicBlock("dynamic_cast.unreachable"));
return T;
+ }
+ }
assert(SrcRecordTy->isRecordType() && "source type must be a record type!");
+ // If the destination is effectively final, the cast succeeds if and only
+ // if the dynamic type of the pointer is exactly the destination type.
+ bool IsExact = !IsDynamicCastToVoid &&
+ CGM.getCodeGenOpts().OptimizationLevel > 0 &&
+ DestRecordTy->getAsCXXRecordDecl()->isEffectivelyFinal() &&
+ CGM.getCXXABI().shouldEmitExactDynamicCast(DestRecordTy);
+
// C++ [expr.dynamic.cast]p4:
// If the value of v is a null pointer value in the pointer case, the result
// is the null pointer value of type T.
bool ShouldNullCheckSrcValue =
- CGM.getCXXABI().shouldDynamicCastCallBeNullChecked(SrcTy->isPointerType(),
- SrcRecordTy);
+ IsExact || CGM.getCXXABI().shouldDynamicCastCallBeNullChecked(
+ SrcTy->isPointerType(), SrcRecordTy);
llvm::BasicBlock *CastNull = nullptr;
llvm::BasicBlock *CastNotNull = nullptr;
@@ -2289,30 +2301,38 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr,
}
llvm::Value *Value;
- if (isDynamicCastToVoid) {
- Value = CGM.getCXXABI().EmitDynamicCastToVoid(*this, ThisAddr, SrcRecordTy,
- DestTy);
+ if (IsDynamicCastToVoid) {
+ Value = CGM.getCXXABI().emitDynamicCastToVoid(*this, ThisAddr, SrcRecordTy);
+ } else if (IsExact) {
+ // If the destination type is effectively final, this pointer points to the
+ // right type if and only if its vptr has the right value.
+ Value = CGM.getCXXABI().emitExactDynamicCast(
+ *this, ThisAddr, SrcRecordTy, DestTy, DestRecordTy, CastEnd, CastNull);
} else {
assert(DestRecordTy->isRecordType() &&
"destination type must be a record type!");
- Value = CGM.getCXXABI().EmitDynamicCastCall(*this, ThisAddr, SrcRecordTy,
+ Value = CGM.getCXXABI().emitDynamicCastCall(*this, ThisAddr, SrcRecordTy,
DestTy, DestRecordTy, CastEnd);
- CastNotNull = Builder.GetInsertBlock();
}
+ CastNotNull = Builder.GetInsertBlock();
+ llvm::Value *NullValue = nullptr;
if (ShouldNullCheckSrcValue) {
EmitBranch(CastEnd);
EmitBlock(CastNull);
+ NullValue = EmitDynamicCastToNull(*this, DestTy);
+ CastNull = Builder.GetInsertBlock();
+
EmitBranch(CastEnd);
}
EmitBlock(CastEnd);
- if (ShouldNullCheckSrcValue) {
+ if (CastNull) {
llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2);
PHI->addIncoming(Value, CastNotNull);
- PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull);
+ PHI->addIncoming(NullValue, CastNull);
Value = PHI;
}