diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /clang/lib/CodeGen/CGExprCXX.cpp | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'clang/lib/CodeGen/CGExprCXX.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGExprCXX.cpp | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 42c1c34c57ad9..d59aa6ce0fb94 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -112,7 +112,8 @@ RValue CodeGenFunction::EmitCXXDestructorCall( commonEmitCXXMemberOrOperatorCall(*this, DtorDecl, This, ImplicitParam, ImplicitParamTy, CE, Args, nullptr); return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(Dtor), Callee, - ReturnValueSlot(), Args); + ReturnValueSlot(), Args, nullptr, + CE ? CE->getExprLoc() : SourceLocation{}); } RValue CodeGenFunction::EmitCXXPseudoDestructorExpr( @@ -380,7 +381,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( IsArrow ? Base->getType()->getPointeeType() : Base->getType(); EmitCXXDestructorCall(GD, Callee, This.getPointer(*this), ThisTy, /*ImplicitParam=*/nullptr, - /*ImplicitParamTy=*/QualType(), nullptr); + /*ImplicitParamTy=*/QualType(), CE); } return RValue::get(nullptr); } @@ -1637,6 +1638,12 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { RValue RV = EmitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs); + // Set !heapallocsite metadata on the call to operator new. + if (getDebugInfo()) + if (auto *newCall = dyn_cast<llvm::CallBase>(RV.getScalarVal())) + getDebugInfo()->addHeapAllocSiteMetadata(newCall, allocType, + E->getExprLoc()); + // If this was a call to a global replaceable allocation function that does // not take an alignment argument, the allocator is known to produce // storage that's suitably aligned for any object that fits, up to a known @@ -1866,10 +1873,13 @@ static void EmitDestroyingObjectDelete(CodeGenFunction &CGF, } /// Emit the code for deleting a single object. -static void EmitObjectDelete(CodeGenFunction &CGF, +/// \return \c true if we started emitting UnconditionalDeleteBlock, \c false +/// if not. +static bool EmitObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, Address Ptr, - QualType ElementType) { + QualType ElementType, + llvm::BasicBlock *UnconditionalDeleteBlock) { // C++11 [expr.delete]p3: // If the static type of the object to be deleted is different from its // dynamic type, the static type shall be a base class of the dynamic type @@ -1916,7 +1926,7 @@ static void EmitObjectDelete(CodeGenFunction &CGF, if (UseVirtualCall) { CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType, Dtor); - return; + return false; } } } @@ -1951,7 +1961,15 @@ static void EmitObjectDelete(CodeGenFunction &CGF, } } + // When optimizing for size, call 'operator delete' unconditionally. + if (CGF.CGM.getCodeGenOpts().OptimizeSize > 1) { + CGF.EmitBlock(UnconditionalDeleteBlock); + CGF.PopCleanupBlock(); + return true; + } + CGF.PopCleanupBlock(); + return false; } namespace { @@ -2028,6 +2046,12 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { Address Ptr = EmitPointerWithAlignment(Arg); // Null check the pointer. + // + // We could avoid this null check if we can determine that the object + // destruction is trivial and doesn't require an array cookie; we can + // unconditionally perform the operator delete call in that case. For now, we + // assume that deleted pointers are null rarely enough that it's better to + // keep the branch. This might be worth revisiting for a -O0 code size win. llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull"); llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end"); @@ -2073,11 +2097,11 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { if (E->isArrayForm()) { EmitArrayDelete(*this, E, Ptr, DeleteTy); + EmitBlock(DeleteEnd); } else { - EmitObjectDelete(*this, E, Ptr, DeleteTy); + if (!EmitObjectDelete(*this, E, Ptr, DeleteTy, DeleteEnd)) + EmitBlock(DeleteEnd); } - - EmitBlock(DeleteEnd); } static bool isGLValueFromPointerDeref(const Expr *E) { |